diff options
Diffstat (limited to 'drivers/platform/x86/intel')
21 files changed, 1523 insertions, 1129 deletions
diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig index 794968bda115..d5a33473e838 100644 --- a/drivers/platform/x86/intel/Kconfig +++ b/drivers/platform/x86/intel/Kconfig @@ -157,13 +157,13 @@ config INTEL_RST as usual. config INTEL_SDSI - tristate "Intel Software Defined Silicon Driver" + tristate "Intel On Demand (Software Defined Silicon) Driver" depends on INTEL_VSEC depends on X86_64 help - This driver enables access to the Intel Software Defined Silicon - interface used to provision silicon features with an authentication - certificate and capability license. + This driver enables access to the Intel On Demand (formerly Software + Defined Silicon) interface used to provision silicon features with an + authentication certificate and capability license. To compile this driver as a module, choose M here: the module will be called intel_sdsi. diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c index b6313ecd190c..b6c06b37862e 100644 --- a/drivers/platform/x86/intel/hid.c +++ b/drivers/platform/x86/intel/hid.c @@ -16,6 +16,25 @@ #include <linux/suspend.h> #include "../dual_accel_detect.h" +enum intel_hid_tablet_sw_mode { + TABLET_SW_AUTO = -1, + TABLET_SW_OFF = 0, + TABLET_SW_AT_EVENT, + TABLET_SW_AT_PROBE, +}; + +static bool enable_5_button_array; +module_param(enable_5_button_array, bool, 0444); +MODULE_PARM_DESC(enable_5_button_array, + "Enable 5 Button Array support. " + "If you need this please report this to: platform-driver-x86@vger.kernel.org"); + +static int enable_sw_tablet_mode = TABLET_SW_AUTO; +module_param(enable_sw_tablet_mode, int, 0444); +MODULE_PARM_DESC(enable_sw_tablet_mode, + "Enable SW_TABLET_MODE reporting -1:auto 0:off 1:at-first-event 2:at-probe. " + "If you need this please report this to: platform-driver-x86@vger.kernel.org"); + /* When NOT in tablet mode, VGBS returns with the flag 0x40 */ #define TABLET_MODE_FLAG BIT(6) @@ -157,7 +176,6 @@ struct intel_hid_priv { struct input_dev *array; struct input_dev *switches; bool wakeup_mode; - bool auto_add_switch; }; #define HID_EVENT_FILTER_UUID "eeec56b3-4442-408f-a792-4edd4d758054" @@ -487,7 +505,8 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) * SW_TABLET_MODE report, in these cases we enable support when receiving * the first event instead of during driver setup. */ - if (!priv->switches && priv->auto_add_switch && (event == 0xcc || event == 0xcd)) { + if (!priv->switches && enable_sw_tablet_mode == TABLET_SW_AT_EVENT && + (event == 0xcc || event == 0xcd)) { dev_info(&device->dev, "switch event received, enable switches supports\n"); err = intel_hid_switches_setup(device); if (err) @@ -592,7 +611,7 @@ static bool button_array_present(struct platform_device *device) return true; } - if (dmi_check_system(button_array_table)) + if (enable_5_button_array || dmi_check_system(button_array_table)) return true; return false; @@ -629,7 +648,14 @@ static int intel_hid_probe(struct platform_device *device) dev_set_drvdata(&device->dev, priv); /* See dual_accel_detect.h for more info on the dual_accel check. */ - priv->auto_add_switch = dmi_check_system(dmi_auto_add_switch) && !dual_accel_detect(); + if (enable_sw_tablet_mode == TABLET_SW_AUTO) { + if (dmi_check_system(dmi_vgbs_allow_list)) + enable_sw_tablet_mode = TABLET_SW_AT_PROBE; + else if (dmi_check_system(dmi_auto_add_switch) && !dual_accel_detect()) + enable_sw_tablet_mode = TABLET_SW_AT_EVENT; + else + enable_sw_tablet_mode = TABLET_SW_OFF; + } err = intel_hid_input_setup(device); if (err) { @@ -646,7 +672,7 @@ static int intel_hid_probe(struct platform_device *device) } /* Setup switches for devices that we know VGBS return correctly */ - if (dmi_check_system(dmi_vgbs_allow_list)) { + if (enable_sw_tablet_mode == TABLET_SW_AT_PROBE) { dev_info(&device->dev, "platform supports switches\n"); err = intel_hid_switches_setup(device); if (err) diff --git a/drivers/platform/x86/intel/ifs/Kconfig b/drivers/platform/x86/intel/ifs/Kconfig index c341a27cc1a3..3eded966757e 100644 --- a/drivers/platform/x86/intel/ifs/Kconfig +++ b/drivers/platform/x86/intel/ifs/Kconfig @@ -1,10 +1,6 @@ config INTEL_IFS tristate "Intel In Field Scan" depends on X86 && CPU_SUP_INTEL && 64BIT && SMP - # Discussion on the list has shown that the sysfs API needs a bit - # more work, mark this as broken for now - depends on BROKEN - select INTEL_IFS_DEVICE help Enable support for the In Field Scan capability in select CPUs. The capability allows for running low level tests via diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c index 27204e3d674d..206a617c2e02 100644 --- a/drivers/platform/x86/intel/ifs/core.c +++ b/drivers/platform/x86/intel/ifs/core.c @@ -4,6 +4,7 @@ #include <linux/module.h> #include <linux/kdev_t.h> #include <linux/semaphore.h> +#include <linux/slab.h> #include <asm/cpu_device_id.h> @@ -22,6 +23,7 @@ MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids); static struct ifs_device ifs_device = { .data = { .integrity_cap_bit = MSR_INTEGRITY_CAPS_PERIODIC_BIST_BIT, + .test_num = 0, }, .misc = { .name = "intel_ifs_0", @@ -34,6 +36,7 @@ static int __init ifs_init(void) { const struct x86_cpu_id *m; u64 msrval; + int ret; m = x86_match_cpu(ifs_cpu_ids); if (!m) @@ -50,20 +53,26 @@ static int __init ifs_init(void) ifs_device.misc.groups = ifs_get_groups(); - if ((msrval & BIT(ifs_device.data.integrity_cap_bit)) && - !misc_register(&ifs_device.misc)) { - down(&ifs_sem); - ifs_load_firmware(ifs_device.misc.this_device); - up(&ifs_sem); - return 0; + if (!(msrval & BIT(ifs_device.data.integrity_cap_bit))) + return -ENODEV; + + ifs_device.data.pkg_auth = kmalloc_array(topology_max_packages(), sizeof(bool), GFP_KERNEL); + if (!ifs_device.data.pkg_auth) + return -ENOMEM; + + ret = misc_register(&ifs_device.misc); + if (ret) { + kfree(ifs_device.data.pkg_auth); + return ret; } - return -ENODEV; + return 0; } static void __exit ifs_exit(void) { misc_deregister(&ifs_device.misc); + kfree(ifs_device.data.pkg_auth); } module_init(ifs_init); diff --git a/drivers/platform/x86/intel/ifs/ifs.h b/drivers/platform/x86/intel/ifs/ifs.h index 73c8e91cf144..046e39304fd5 100644 --- a/drivers/platform/x86/intel/ifs/ifs.h +++ b/drivers/platform/x86/intel/ifs/ifs.h @@ -33,13 +33,23 @@ * The driver loads the tests into memory reserved BIOS local to each CPU * socket in a two step process using writes to MSRs to first load the * SHA hashes for the test. Then the tests themselves. Status MSRs provide - * feedback on the success/failure of these steps. When a new test file - * is installed it can be loaded by writing to the driver reload file:: + * feedback on the success/failure of these steps. * - * # echo 1 > /sys/devices/virtual/misc/intel_ifs_0/reload + * The test files are kept in a fixed location: /lib/firmware/intel/ifs_0/ + * For e.g if there are 3 test files, they would be named in the following + * fashion: + * ff-mm-ss-01.scan + * ff-mm-ss-02.scan + * ff-mm-ss-03.scan + * (where ff refers to family, mm indicates model and ss indicates stepping) * - * Similar to microcode, the current version of the scan tests is stored - * in a fixed location: /lib/firmware/intel/ifs.0/family-model-stepping.scan + * A different test file can be loaded by writing the numerical portion + * (e.g 1, 2 or 3 in the above scenario) into the curent_batch file. + * To load ff-mm-ss-02.scan, the following command can be used:: + * + * # echo 2 > /sys/devices/virtual/misc/intel_ifs_0/current_batch + * + * The above file can also be read to know the currently loaded image. * * Running tests * ------------- @@ -191,20 +201,26 @@ union ifs_status { * struct ifs_data - attributes related to intel IFS driver * @integrity_cap_bit: MSR_INTEGRITY_CAPS bit enumerating this test * @loaded_version: stores the currently loaded ifs image version. + * @pkg_auth: array of bool storing per package auth status * @loaded: If a valid test binary has been loaded into the memory * @loading_error: Error occurred on another CPU while loading image * @valid_chunks: number of chunks which could be validated. * @status: it holds simple status pass/fail/untested * @scan_details: opaque scan status code from h/w + * @cur_batch: number indicating the currently loaded test file + * @test_num: number indicating the test type */ struct ifs_data { int integrity_cap_bit; + bool *pkg_auth; int loaded_version; bool loaded; bool loading_error; int valid_chunks; int status; u64 scan_details; + u32 cur_batch; + int test_num; }; struct ifs_work { @@ -225,10 +241,8 @@ static inline struct ifs_data *ifs_get_data(struct device *dev) return &d->data; } -void ifs_load_firmware(struct device *dev); +int ifs_load_firmware(struct device *dev); int do_core_test(int cpu, struct device *dev); const struct attribute_group **ifs_get_groups(void); -extern struct semaphore ifs_sem; - #endif diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c index d056617ddc85..c5c24e6fdc43 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -3,27 +3,30 @@ #include <linux/firmware.h> #include <asm/cpu.h> -#include <linux/slab.h> #include <asm/microcode_intel.h> #include "ifs.h" -struct ifs_header { - u32 header_ver; - u32 blob_revision; - u32 date; - u32 processor_sig; - u32 check_sum; - u32 loader_rev; - u32 processor_flags; - u32 metadata_size; - u32 total_size; - u32 fusa_info; - u64 reserved; +#define IFS_CHUNK_ALIGNMENT 256 +union meta_data { + struct { + u32 meta_type; // metadata type + u32 meta_size; // size of this entire struct including hdrs. + u32 test_type; // IFS test type + u32 fusa_info; // Fusa info + u32 total_images; // Total number of images + u32 current_image; // Current Image # + u32 total_chunks; // Total number of chunks in this image + u32 starting_chunk; // Starting chunk number in this image + u32 size_per_chunk; // size of each chunk + u32 chunks_per_stride; // number of chunks in a stride + }; + u8 padding[IFS_CHUNK_ALIGNMENT]; }; -#define IFS_HEADER_SIZE (sizeof(struct ifs_header)) -static struct ifs_header *ifs_header_ptr; /* pointer to the ifs image header */ +#define IFS_HEADER_SIZE (sizeof(struct microcode_header_intel)) +#define META_TYPE_IFS 1 +static struct microcode_header_intel *ifs_header_ptr; /* pointer to the ifs image header */ static u64 ifs_hash_ptr; /* Address of ifs metadata (hash) */ static u64 ifs_test_image_ptr; /* 256B aligned address of test pattern */ static DECLARE_COMPLETION(ifs_done); @@ -44,6 +47,38 @@ static const char * const scan_authentication_status[] = { [2] = "Chunk authentication error. The hash of chunk did not match expected value" }; +#define MC_HEADER_META_TYPE_END (0) + +struct metadata_header { + unsigned int type; + unsigned int blk_size; +}; + +static struct metadata_header *find_meta_data(void *ucode, unsigned int meta_type) +{ + struct metadata_header *meta_header; + unsigned long data_size, total_meta; + unsigned long meta_size = 0; + + data_size = get_datasize(ucode); + total_meta = ((struct microcode_intel *)ucode)->hdr.metasize; + if (!total_meta) + return NULL; + + meta_header = (ucode + MC_HEADER_SIZE + data_size) - total_meta; + + while (meta_header->type != MC_HEADER_META_TYPE_END && + meta_header->blk_size && + meta_size < total_meta) { + meta_size += meta_header->blk_size; + if (meta_header->type == meta_type) + return meta_header; + + meta_header = (void *)meta_header + meta_header->blk_size; + } + return NULL; +} + /* * To copy scan hashes and authenticate test chunks, the initiating cpu must point * to the EDX:EAX to the test image in linear address. @@ -111,6 +146,41 @@ done: complete(&ifs_done); } +static int validate_ifs_metadata(struct device *dev) +{ + struct ifs_data *ifsd = ifs_get_data(dev); + union meta_data *ifs_meta; + char test_file[64]; + int ret = -EINVAL; + + snprintf(test_file, sizeof(test_file), "%02x-%02x-%02x-%02x.scan", + boot_cpu_data.x86, boot_cpu_data.x86_model, + boot_cpu_data.x86_stepping, ifsd->cur_batch); + + ifs_meta = (union meta_data *)find_meta_data(ifs_header_ptr, META_TYPE_IFS); + if (!ifs_meta) { + dev_err(dev, "IFS Metadata missing in file %s\n", test_file); + return ret; + } + + ifs_test_image_ptr = (u64)ifs_meta + sizeof(union meta_data); + + /* Scan chunk start must be 256 byte aligned */ + if (!IS_ALIGNED(ifs_test_image_ptr, IFS_CHUNK_ALIGNMENT)) { + dev_err(dev, "Scan pattern is not aligned on %d bytes aligned in %s\n", + IFS_CHUNK_ALIGNMENT, test_file); + return ret; + } + + if (ifs_meta->current_image != ifsd->cur_batch) { + dev_warn(dev, "Mismatch between filename %s and batch metadata 0x%02x\n", + test_file, ifs_meta->current_image); + return ret; + } + + return 0; +} + /* * IFS requires scan chunks authenticated per each socket in the platform. * Once the test chunk is authenticated, it is automatically copied to secured memory @@ -118,131 +188,83 @@ done: */ static int scan_chunks_sanity_check(struct device *dev) { - int metadata_size, curr_pkg, cpu, ret = -ENOMEM; struct ifs_data *ifsd = ifs_get_data(dev); - bool *package_authenticated; struct ifs_work local_work; - char *test_ptr; + int curr_pkg, cpu, ret; - package_authenticated = kcalloc(topology_max_packages(), sizeof(bool), GFP_KERNEL); - if (!package_authenticated) + memset(ifsd->pkg_auth, 0, (topology_max_packages() * sizeof(bool))); + ret = validate_ifs_metadata(dev); + if (ret) return ret; - metadata_size = ifs_header_ptr->metadata_size; - - /* Spec says that if the Meta Data Size = 0 then it should be treated as 2000 */ - if (metadata_size == 0) - metadata_size = 2000; - - /* Scan chunk start must be 256 byte aligned */ - if ((metadata_size + IFS_HEADER_SIZE) % 256) { - dev_err(dev, "Scan pattern offset within the binary is not 256 byte aligned\n"); - return -EINVAL; - } - - test_ptr = (char *)ifs_header_ptr + IFS_HEADER_SIZE + metadata_size; ifsd->loading_error = false; - - ifs_test_image_ptr = (u64)test_ptr; - ifsd->loaded_version = ifs_header_ptr->blob_revision; + ifsd->loaded_version = ifs_header_ptr->rev; /* copy the scan hash and authenticate per package */ cpus_read_lock(); for_each_online_cpu(cpu) { curr_pkg = topology_physical_package_id(cpu); - if (package_authenticated[curr_pkg]) + if (ifsd->pkg_auth[curr_pkg]) continue; reinit_completion(&ifs_done); local_work.dev = dev; INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks); schedule_work_on(cpu, &local_work.w); wait_for_completion(&ifs_done); - if (ifsd->loading_error) + if (ifsd->loading_error) { + ret = -EIO; goto out; - package_authenticated[curr_pkg] = 1; + } + ifsd->pkg_auth[curr_pkg] = 1; } ret = 0; out: cpus_read_unlock(); - kfree(package_authenticated); return ret; } -static int ifs_sanity_check(struct device *dev, - const struct microcode_header_intel *mc_header) +static int image_sanity_check(struct device *dev, const struct microcode_header_intel *data) { - unsigned long total_size, data_size; - u32 sum, *mc; - - total_size = get_totalsize(mc_header); - data_size = get_datasize(mc_header); + struct ucode_cpu_info uci; - if ((data_size + MC_HEADER_SIZE > total_size) || (total_size % sizeof(u32))) { - dev_err(dev, "bad ifs data file size.\n"); + /* Provide a specific error message when loading an older/unsupported image */ + if (data->hdrver != MC_HEADER_TYPE_IFS) { + dev_err(dev, "Header version %d not supported\n", data->hdrver); return -EINVAL; } - if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { - dev_err(dev, "invalid/unknown ifs update format.\n"); + if (intel_microcode_sanity_check((void *)data, true, MC_HEADER_TYPE_IFS)) { + dev_err(dev, "sanity check failed\n"); return -EINVAL; } - mc = (u32 *)mc_header; - sum = 0; - for (int i = 0; i < total_size / sizeof(u32); i++) - sum += mc[i]; + intel_cpu_collect_info(&uci); - if (sum) { - dev_err(dev, "bad ifs data checksum, aborting.\n"); + if (!intel_find_matching_signature((void *)data, + uci.cpu_sig.sig, + uci.cpu_sig.pf)) { + dev_err(dev, "cpu signature, processor flags not matching\n"); return -EINVAL; } return 0; } -static bool find_ifs_matching_signature(struct device *dev, struct ucode_cpu_info *uci, - const struct microcode_header_intel *shdr) -{ - unsigned int mc_size; - - mc_size = get_totalsize(shdr); - - if (!mc_size || ifs_sanity_check(dev, shdr) < 0) { - dev_err(dev, "ifs sanity check failure\n"); - return false; - } - - if (!intel_cpu_signatures_match(uci->cpu_sig.sig, uci->cpu_sig.pf, shdr->sig, shdr->pf)) { - dev_err(dev, "ifs signature, pf not matching\n"); - return false; - } - - return true; -} - -static bool ifs_image_sanity_check(struct device *dev, const struct microcode_header_intel *data) -{ - struct ucode_cpu_info uci; - - intel_cpu_collect_info(&uci); - - return find_ifs_matching_signature(dev, &uci, data); -} - /* * Load ifs image. Before loading ifs module, the ifs image must be located - * in /lib/firmware/intel/ifs and named as {family/model/stepping}.{testname}. + * in /lib/firmware/intel/ifs_x/ and named as family-model-stepping-02x.{testname}. */ -void ifs_load_firmware(struct device *dev) +int ifs_load_firmware(struct device *dev) { struct ifs_data *ifsd = ifs_get_data(dev); const struct firmware *fw; - char scan_path[32]; - int ret; + char scan_path[64]; + int ret = -EINVAL; - snprintf(scan_path, sizeof(scan_path), "intel/ifs/%02x-%02x-%02x.scan", - boot_cpu_data.x86, boot_cpu_data.x86_model, boot_cpu_data.x86_stepping); + snprintf(scan_path, sizeof(scan_path), "intel/ifs_%d/%02x-%02x-%02x-%02x.scan", + ifsd->test_num, boot_cpu_data.x86, boot_cpu_data.x86_model, + boot_cpu_data.x86_stepping, ifsd->cur_batch); ret = request_firmware_direct(&fw, scan_path, dev); if (ret) { @@ -250,17 +272,21 @@ void ifs_load_firmware(struct device *dev) goto done; } - if (!ifs_image_sanity_check(dev, (struct microcode_header_intel *)fw->data)) { - dev_err(dev, "ifs header sanity check failed\n"); + ret = image_sanity_check(dev, (struct microcode_header_intel *)fw->data); + if (ret) goto release; - } - ifs_header_ptr = (struct ifs_header *)fw->data; + ifs_header_ptr = (struct microcode_header_intel *)fw->data; ifs_hash_ptr = (u64)(ifs_header_ptr + 1); ret = scan_chunks_sanity_check(dev); + if (ret) + dev_err(dev, "Load failure for batch: %02x\n", ifsd->cur_batch); + release: release_firmware(fw); done: ifsd->loaded = (ret == 0); + + return ret; } diff --git a/drivers/platform/x86/intel/ifs/runtest.c b/drivers/platform/x86/intel/ifs/runtest.c index b2ca2bb4501f..0bfd8fcdd7e8 100644 --- a/drivers/platform/x86/intel/ifs/runtest.c +++ b/drivers/platform/x86/intel/ifs/runtest.c @@ -78,14 +78,16 @@ static void message_not_tested(struct device *dev, int cpu, union ifs_status sta static void message_fail(struct device *dev, int cpu, union ifs_status status) { + struct ifs_data *ifsd = ifs_get_data(dev); + /* * control_error is set when the microcode runs into a problem * loading the image from the reserved BIOS memory, or it has * been corrupted. Reloading the image may fix this issue. */ if (status.control_error) { - dev_err(dev, "CPU(s) %*pbl: could not execute from loaded scan image\n", - cpumask_pr_args(cpu_smt_mask(cpu))); + dev_err(dev, "CPU(s) %*pbl: could not execute from loaded scan image. Batch: %02x version: 0x%x\n", + cpumask_pr_args(cpu_smt_mask(cpu)), ifsd->cur_batch, ifsd->loaded_version); } /* @@ -96,8 +98,8 @@ static void message_fail(struct device *dev, int cpu, union ifs_status status) * the core being tested. */ if (status.signature_error) { - dev_err(dev, "CPU(s) %*pbl: test signature incorrect.\n", - cpumask_pr_args(cpu_smt_mask(cpu))); + dev_err(dev, "CPU(s) %*pbl: test signature incorrect. Batch: %02x version: 0x%x\n", + cpumask_pr_args(cpu_smt_mask(cpu)), ifsd->cur_batch, ifsd->loaded_version); } } diff --git a/drivers/platform/x86/intel/ifs/sysfs.c b/drivers/platform/x86/intel/ifs/sysfs.c index 37d8380d6fa8..ee636a76b083 100644 --- a/drivers/platform/x86/intel/ifs/sysfs.c +++ b/drivers/platform/x86/intel/ifs/sysfs.c @@ -13,7 +13,7 @@ * Protects against simultaneous tests on multiple cores, or * reloading can file while a test is in progress */ -DEFINE_SEMAPHORE(ifs_sem); +static DEFINE_SEMAPHORE(ifs_sem); /* * The sysfs interface to check additional details of last test @@ -87,33 +87,42 @@ static ssize_t run_test_store(struct device *dev, static DEVICE_ATTR_WO(run_test); -/* - * Reload the IFS image. When user wants to install new IFS image - */ -static ssize_t reload_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t current_batch_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct ifs_data *ifsd = ifs_get_data(dev); - bool res; - + unsigned int cur_batch; + int rc; - if (kstrtobool(buf, &res)) + rc = kstrtouint(buf, 0, &cur_batch); + if (rc < 0 || cur_batch > 0xff) return -EINVAL; - if (!res) - return count; if (down_interruptible(&ifs_sem)) return -EINTR; - ifs_load_firmware(dev); + ifsd->cur_batch = cur_batch; + + rc = ifs_load_firmware(dev); up(&ifs_sem); - return ifsd->loaded ? count : -ENODEV; + return (rc == 0) ? count : rc; +} + +static ssize_t current_batch_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ifs_data *ifsd = ifs_get_data(dev); + + if (!ifsd->loaded) + return sysfs_emit(buf, "none\n"); + else + return sysfs_emit(buf, "0x%02x\n", ifsd->cur_batch); } -static DEVICE_ATTR_WO(reload); +static DEVICE_ATTR_RW(current_batch); /* * Display currently loaded IFS image version. @@ -136,7 +145,7 @@ static struct attribute *plat_ifs_attrs[] = { &dev_attr_details.attr, &dev_attr_status.attr, &dev_attr_run_test.attr, - &dev_attr_reload.attr, + &dev_attr_current_batch.attr, &dev_attr_image_version.attr, NULL }; diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c index 1cf958983e86..b2342b3d78c7 100644 --- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -185,7 +185,8 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, cfg.init_data = &init_data; cfg.ena_gpiod = int3472->regulator.gpio; - int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc, + int3472->regulator.rdev = regulator_register(int3472->dev, + &int3472->regulator.rdesc, &cfg); if (IS_ERR(int3472->regulator.rdev)) { ret = PTR_ERR(int3472->regulator.rdev); diff --git a/drivers/platform/x86/intel/pmc/Makefile b/drivers/platform/x86/intel/pmc/Makefile index 8966fcdc0e1d..f96bc2e19503 100644 --- a/drivers/platform/x86/intel/pmc/Makefile +++ b/drivers/platform/x86/intel/pmc/Makefile @@ -3,7 +3,8 @@ # Intel x86 Platform-Specific Drivers # -intel_pmc_core-y := core.o +intel_pmc_core-y := core.o spt.o cnp.o icl.o tgl.o \ + adl.o mtl.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o intel_pmc_core_pltdrv-y := pltdrv.o obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c new file mode 100644 index 000000000000..5cbd40979f2a --- /dev/null +++ b/drivers/platform/x86/intel/pmc/adl.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains platform specific structure definitions + * and init function used by Alder Lake PCH. + * + * Copyright (c) 2022, Intel Corporation. + * All Rights Reserved. + * + */ + +#include "core.h" + +/* Alder Lake: PGD PFET Enable Ack Status Register(s) bitmap */ +const struct pmc_bit_map adl_pfear_map[] = { + {"SPI/eSPI", BIT(2)}, + {"XHCI", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"SPC", BIT(6)}, + {"GBE", BIT(7)}, + + {"SATA", BIT(0)}, + {"HDA_PGD0", BIT(1)}, + {"HDA_PGD1", BIT(2)}, + {"HDA_PGD2", BIT(3)}, + {"HDA_PGD3", BIT(4)}, + {"SPD", BIT(5)}, + {"LPSS", BIT(6)}, + + {"SMB", BIT(0)}, + {"ISH", BIT(1)}, + {"ITH", BIT(3)}, + + {"XDCI", BIT(1)}, + {"DCI", BIT(2)}, + {"CSE", BIT(3)}, + {"CSME_KVM", BIT(4)}, + {"CSME_PMT", BIT(5)}, + {"CSME_CLINK", BIT(6)}, + {"CSME_PTIO", BIT(7)}, + + {"CSME_USBR", BIT(0)}, + {"CSME_SUSRAM", BIT(1)}, + {"CSME_SMT1", BIT(2)}, + {"CSME_SMS2", BIT(4)}, + {"CSME_SMS1", BIT(5)}, + {"CSME_RTC", BIT(6)}, + {"CSME_PSF", BIT(7)}, + + {"CNVI", BIT(3)}, + {"HDA_PGD4", BIT(2)}, + {"HDA_PGD5", BIT(3)}, + {"HDA_PGD6", BIT(4)}, + {} +}; + +const struct pmc_bit_map *ext_adl_pfear_map[] = { + /* + * Check intel_pmc_core_ids[] users of cnp_reg_map for + * a list of core SoCs using this. + */ + adl_pfear_map, + NULL +}; + +const struct pmc_bit_map adl_ltr_show_map[] = { + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, + {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, + {"SATA", CNP_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, + {"XHCI", CNP_PMC_LTR_XHCI}, + {"SOUTHPORT_F", ADL_PMC_LTR_SPF}, + {"ME", CNP_PMC_LTR_ME}, + /* EVA is Enterprise Value Add, doesn't really exist on PCH */ + {"SATA1", CNP_PMC_LTR_EVA}, + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, + {"HD_AUDIO", CNP_PMC_LTR_AZ}, + {"CNV", CNP_PMC_LTR_CNV}, + {"LPSS", CNP_PMC_LTR_LPSS}, + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, + {"SATA2", CNP_PMC_LTR_CAM}, + {"ESPI", CNP_PMC_LTR_ESPI}, + {"SCC", CNP_PMC_LTR_SCC}, + {"ISH", CNP_PMC_LTR_ISH}, + {"UFSX2", CNP_PMC_LTR_UFSX2}, + {"EMMC", CNP_PMC_LTR_EMMC}, + /* + * Check intel_pmc_core_ids[] users of cnp_reg_map for + * a list of core SoCs using this. + */ + {"WIGIG", ICL_PMC_LTR_WIGIG}, + {"THC0", TGL_PMC_LTR_THC0}, + {"THC1", TGL_PMC_LTR_THC1}, + {"SOUTHPORT_G", CNP_PMC_LTR_RESERVED}, + + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, + {} +}; + +const struct pmc_bit_map adl_clocksource_status_map[] = { + {"CLKPART1_OFF_STS", BIT(0)}, + {"CLKPART2_OFF_STS", BIT(1)}, + {"CLKPART3_OFF_STS", BIT(2)}, + {"CLKPART4_OFF_STS", BIT(3)}, + {"CLKPART5_OFF_STS", BIT(4)}, + {"CLKPART6_OFF_STS", BIT(5)}, + {"CLKPART7_OFF_STS", BIT(6)}, + {"CLKPART8_OFF_STS", BIT(7)}, + {"PCIE0PLL_OFF_STS", BIT(10)}, + {"PCIE1PLL_OFF_STS", BIT(11)}, + {"PCIE2PLL_OFF_STS", BIT(12)}, + {"PCIE3PLL_OFF_STS", BIT(13)}, + {"PCIE4PLL_OFF_STS", BIT(14)}, + {"PCIE5PLL_OFF_STS", BIT(15)}, + {"PCIE6PLL_OFF_STS", BIT(16)}, + {"USB2PLL_OFF_STS", BIT(18)}, + {"OCPLL_OFF_STS", BIT(22)}, + {"AUDIOPLL_OFF_STS", BIT(23)}, + {"GBEPLL_OFF_STS", BIT(24)}, + {"Fast_XTAL_Osc_OFF_STS", BIT(25)}, + {"AC_Ring_Osc_OFF_STS", BIT(26)}, + {"MC_Ring_Osc_OFF_STS", BIT(27)}, + {"SATAPLL_OFF_STS", BIT(29)}, + {"USB3PLL_OFF_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map adl_power_gating_status_0_map[] = { + {"PMC_PGD0_PG_STS", BIT(0)}, + {"DMI_PGD0_PG_STS", BIT(1)}, + {"ESPISPI_PGD0_PG_STS", BIT(2)}, + {"XHCI_PGD0_PG_STS", BIT(3)}, + {"SPA_PGD0_PG_STS", BIT(4)}, + {"SPB_PGD0_PG_STS", BIT(5)}, + {"SPC_PGD0_PG_STS", BIT(6)}, + {"GBE_PGD0_PG_STS", BIT(7)}, + {"SATA_PGD0_PG_STS", BIT(8)}, + {"DSP_PGD0_PG_STS", BIT(9)}, + {"DSP_PGD1_PG_STS", BIT(10)}, + {"DSP_PGD2_PG_STS", BIT(11)}, + {"DSP_PGD3_PG_STS", BIT(12)}, + {"SPD_PGD0_PG_STS", BIT(13)}, + {"LPSS_PGD0_PG_STS", BIT(14)}, + {"SMB_PGD0_PG_STS", BIT(16)}, + {"ISH_PGD0_PG_STS", BIT(17)}, + {"NPK_PGD0_PG_STS", BIT(19)}, + {"PECI_PGD0_PG_STS", BIT(21)}, + {"XDCI_PGD0_PG_STS", BIT(25)}, + {"EXI_PGD0_PG_STS", BIT(26)}, + {"CSE_PGD0_PG_STS", BIT(27)}, + {"KVMCC_PGD0_PG_STS", BIT(28)}, + {"PMT_PGD0_PG_STS", BIT(29)}, + {"CLINK_PGD0_PG_STS", BIT(30)}, + {"PTIO_PGD0_PG_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map adl_power_gating_status_1_map[] = { + {"USBR0_PGD0_PG_STS", BIT(0)}, + {"SMT1_PGD0_PG_STS", BIT(2)}, + {"CSMERTC_PGD0_PG_STS", BIT(6)}, + {"CSMEPSF_PGD0_PG_STS", BIT(7)}, + {"CNVI_PGD0_PG_STS", BIT(19)}, + {"DSP_PGD4_PG_STS", BIT(26)}, + {"SPG_PGD0_PG_STS", BIT(27)}, + {"SPE_PGD0_PG_STS", BIT(28)}, + {} +}; + +const struct pmc_bit_map adl_power_gating_status_2_map[] = { + {"THC0_PGD0_PG_STS", BIT(7)}, + {"THC1_PGD0_PG_STS", BIT(8)}, + {"SPF_PGD0_PG_STS", BIT(14)}, + {} +}; + +const struct pmc_bit_map adl_d3_status_0_map[] = { + {"ISH_D3_STS", BIT(2)}, + {"LPSS_D3_STS", BIT(3)}, + {"XDCI_D3_STS", BIT(4)}, + {"XHCI_D3_STS", BIT(5)}, + {"SPA_D3_STS", BIT(12)}, + {"SPB_D3_STS", BIT(13)}, + {"SPC_D3_STS", BIT(14)}, + {"SPD_D3_STS", BIT(15)}, + {"SPE_D3_STS", BIT(16)}, + {"DSP_D3_STS", BIT(19)}, + {"SATA_D3_STS", BIT(20)}, + {"DMI_D3_STS", BIT(22)}, + {} +}; + +const struct pmc_bit_map adl_d3_status_1_map[] = { + {"GBE_D3_STS", BIT(19)}, + {"CNVI_D3_STS", BIT(27)}, + {} +}; + +const struct pmc_bit_map adl_d3_status_2_map[] = { + {"CSMERTC_D3_STS", BIT(1)}, + {"CSE_D3_STS", BIT(4)}, + {"KVMCC_D3_STS", BIT(5)}, + {"USBR0_D3_STS", BIT(6)}, + {"SMT1_D3_STS", BIT(8)}, + {"PTIO_D3_STS", BIT(16)}, + {"PMT_D3_STS", BIT(17)}, + {} +}; + +const struct pmc_bit_map adl_d3_status_3_map[] = { + {"THC0_D3_STS", BIT(14)}, + {"THC1_D3_STS", BIT(15)}, + {} +}; + +const struct pmc_bit_map adl_vnn_req_status_0_map[] = { + {"ISH_VNN_REQ_STS", BIT(2)}, + {"ESPISPI_VNN_REQ_STS", BIT(18)}, + {"DSP_VNN_REQ_STS", BIT(19)}, + {} +}; + +const struct pmc_bit_map adl_vnn_req_status_1_map[] = { + {"NPK_VNN_REQ_STS", BIT(4)}, + {"EXI_VNN_REQ_STS", BIT(9)}, + {"GBE_VNN_REQ_STS", BIT(19)}, + {"SMB_VNN_REQ_STS", BIT(25)}, + {"CNVI_VNN_REQ_STS", BIT(27)}, + {} +}; + +const struct pmc_bit_map adl_vnn_req_status_2_map[] = { + {"CSMERTC_VNN_REQ_STS", BIT(1)}, + {"CSE_VNN_REQ_STS", BIT(4)}, + {"SMT1_VNN_REQ_STS", BIT(8)}, + {"CLINK_VNN_REQ_STS", BIT(14)}, + {"GPIOCOM4_VNN_REQ_STS", BIT(20)}, + {"GPIOCOM3_VNN_REQ_STS", BIT(21)}, + {"GPIOCOM2_VNN_REQ_STS", BIT(22)}, + {"GPIOCOM1_VNN_REQ_STS", BIT(23)}, + {"GPIOCOM0_VNN_REQ_STS", BIT(24)}, + {} +}; + +const struct pmc_bit_map adl_vnn_req_status_3_map[] = { + {"GPIOCOM5_VNN_REQ_STS", BIT(11)}, + {} +}; + +const struct pmc_bit_map adl_vnn_misc_status_map[] = { + {"CPU_C10_REQ_STS", BIT(0)}, + {"PCIe_LPM_En_REQ_STS", BIT(3)}, + {"ITH_REQ_STS", BIT(5)}, + {"CNVI_REQ_STS", BIT(6)}, + {"ISH_REQ_STS", BIT(7)}, + {"USB2_SUS_PG_Sys_REQ_STS", BIT(10)}, + {"PCIe_Clk_REQ_STS", BIT(12)}, + {"MPHY_Core_DL_REQ_STS", BIT(16)}, + {"Break-even_En_REQ_STS", BIT(17)}, + {"MPHY_SUS_REQ_STS", BIT(22)}, + {"xDCI_attached_REQ_STS", BIT(24)}, + {} +}; + +const struct pmc_bit_map *adl_lpm_maps[] = { + adl_clocksource_status_map, + adl_power_gating_status_0_map, + adl_power_gating_status_1_map, + adl_power_gating_status_2_map, + adl_d3_status_0_map, + adl_d3_status_1_map, + adl_d3_status_2_map, + adl_d3_status_3_map, + adl_vnn_req_status_0_map, + adl_vnn_req_status_1_map, + adl_vnn_req_status_2_map, + adl_vnn_req_status_3_map, + adl_vnn_misc_status_map, + tgl_signal_status_map, + NULL +}; + +const struct pmc_reg_map adl_reg_map = { + .pfear_sts = ext_adl_pfear_map, + .slp_s0_offset = ADL_PMC_SLP_S0_RES_COUNTER_OFFSET, + .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, + .ltr_show_sts = adl_ltr_show_map, + .msr_sts = msr_map, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .regmap_length = CNP_PMC_MMIO_REG_LEN, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, + .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, + .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, + .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, + .lpm_num_modes = ADL_LPM_NUM_MODES, + .lpm_num_maps = ADL_LPM_NUM_MAPS, + .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, + .etr3_offset = ETR3_OFFSET, + .lpm_sts_latch_en_offset = ADL_LPM_STATUS_LATCH_EN_OFFSET, + .lpm_priority_offset = ADL_LPM_PRI_OFFSET, + .lpm_en_offset = ADL_LPM_EN_OFFSET, + .lpm_residency_offset = ADL_LPM_RESIDENCY_OFFSET, + .lpm_sts = adl_lpm_maps, + .lpm_status_offset = ADL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET, +}; + +void adl_core_configure(struct pmc_dev *pmcdev) +{ + /* Due to a hardware limitation, the GBE LTR blocks PC10 + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); + pmc_core_send_ltr_ignore(pmcdev, 3); +} + +void adl_core_init(struct pmc_dev *pmcdev) +{ + pmcdev->map = &adl_reg_map; + pmcdev->core_configure = adl_core_configure; +} diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c new file mode 100644 index 000000000000..7fb38815c4eb --- /dev/null +++ b/drivers/platform/x86/intel/pmc/cnp.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains platform specific structure definitions + * and init function used by Cannon Lake Point PCH. + * + * Copyright (c) 2022, Intel Corporation. + * All Rights Reserved. + * + */ + +#include "core.h" + +/* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */ +const struct pmc_bit_map cnp_pfear_map[] = { + {"PMC", BIT(0)}, + {"OPI-DMI", BIT(1)}, + {"SPI/eSPI", BIT(2)}, + {"XHCI", BIT(3)}, + {"SPA", BIT(4)}, + {"SPB", BIT(5)}, + {"SPC", BIT(6)}, + {"GBE", BIT(7)}, + + {"SATA", BIT(0)}, + {"HDA_PGD0", BIT(1)}, + {"HDA_PGD1", BIT(2)}, + {"HDA_PGD2", BIT(3)}, + {"HDA_PGD3", BIT(4)}, + {"SPD", BIT(5)}, + {"LPSS", BIT(6)}, + {"LPC", BIT(7)}, + + {"SMB", BIT(0)}, + {"ISH", BIT(1)}, + {"P2SB", BIT(2)}, + {"NPK_VNN", BIT(3)}, + {"SDX", BIT(4)}, + {"SPE", BIT(5)}, + {"Fuse", BIT(6)}, + {"SBR8", BIT(7)}, + + {"CSME_FSC", BIT(0)}, + {"USB3_OTG", BIT(1)}, + {"EXI", BIT(2)}, + {"CSE", BIT(3)}, + {"CSME_KVM", BIT(4)}, + {"CSME_PMT", BIT(5)}, + {"CSME_CLINK", BIT(6)}, + {"CSME_PTIO", BIT(7)}, + + {"CSME_USBR", BIT(0)}, + {"CSME_SUSRAM", BIT(1)}, + {"CSME_SMT1", BIT(2)}, + {"CSME_SMT4", BIT(3)}, + {"CSME_SMS2", BIT(4)}, + {"CSME_SMS1", BIT(5)}, + {"CSME_RTC", BIT(6)}, + {"CSME_PSF", BIT(7)}, + + {"SBR0", BIT(0)}, + {"SBR1", BIT(1)}, + {"SBR2", BIT(2)}, + {"SBR3", BIT(3)}, + {"SBR4", BIT(4)}, + {"SBR5", BIT(5)}, + {"CSME_PECI", BIT(6)}, + {"PSF1", BIT(7)}, + + {"PSF2", BIT(0)}, + {"PSF3", BIT(1)}, + {"PSF4", BIT(2)}, + {"CNVI", BIT(3)}, + {"UFS0", BIT(4)}, + {"EMMC", BIT(5)}, + {"SPF", BIT(6)}, + {"SBR6", BIT(7)}, + + {"SBR7", BIT(0)}, + {"NPK_AON", BIT(1)}, + {"HDA_PGD4", BIT(2)}, + {"HDA_PGD5", BIT(3)}, + {"HDA_PGD6", BIT(4)}, + {"PSF6", BIT(5)}, + {"PSF7", BIT(6)}, + {"PSF8", BIT(7)}, + {} +}; + +const struct pmc_bit_map *ext_cnp_pfear_map[] = { + /* + * Check intel_pmc_core_ids[] users of cnp_reg_map for + * a list of core SoCs using this. + */ + cnp_pfear_map, + NULL +}; + +const struct pmc_bit_map cnp_slps0_dbg0_map[] = { + {"AUDIO_D3", BIT(0)}, + {"OTG_D3", BIT(1)}, + {"XHCI_D3", BIT(2)}, + {"LPIO_D3", BIT(3)}, + {"SDX_D3", BIT(4)}, + {"SATA_D3", BIT(5)}, + {"UFS0_D3", BIT(6)}, + {"UFS1_D3", BIT(7)}, + {"EMMC_D3", BIT(8)}, + {} +}; + +const struct pmc_bit_map cnp_slps0_dbg1_map[] = { + {"SDIO_PLL_OFF", BIT(0)}, + {"USB2_PLL_OFF", BIT(1)}, + {"AUDIO_PLL_OFF", BIT(2)}, + {"OC_PLL_OFF", BIT(3)}, + {"MAIN_PLL_OFF", BIT(4)}, + {"XOSC_OFF", BIT(5)}, + {"LPC_CLKS_GATED", BIT(6)}, + {"PCIE_CLKREQS_IDLE", BIT(7)}, + {"AUDIO_ROSC_OFF", BIT(8)}, + {"HPET_XOSC_CLK_REQ", BIT(9)}, + {"PMC_ROSC_SLOW_CLK", BIT(10)}, + {"AON2_ROSC_GATED", BIT(11)}, + {"CLKACKS_DEASSERTED", BIT(12)}, + {} +}; + +const struct pmc_bit_map cnp_slps0_dbg2_map[] = { + {"MPHY_CORE_GATED", BIT(0)}, + {"CSME_GATED", BIT(1)}, + {"USB2_SUS_GATED", BIT(2)}, + {"DYN_FLEX_IO_IDLE", BIT(3)}, + {"GBE_NO_LINK", BIT(4)}, + {"THERM_SEN_DISABLED", BIT(5)}, + {"PCIE_LOW_POWER", BIT(6)}, + {"ISH_VNNAON_REQ_ACT", BIT(7)}, + {"ISH_VNN_REQ_ACT", BIT(8)}, + {"CNV_VNNAON_REQ_ACT", BIT(9)}, + {"CNV_VNN_REQ_ACT", BIT(10)}, + {"NPK_VNNON_REQ_ACT", BIT(11)}, + {"PMSYNC_STATE_IDLE", BIT(12)}, + {"ALST_GT_THRES", BIT(13)}, + {"PMC_ARC_PG_READY", BIT(14)}, + {} +}; + +const struct pmc_bit_map *cnp_slps0_dbg_maps[] = { + cnp_slps0_dbg0_map, + cnp_slps0_dbg1_map, + cnp_slps0_dbg2_map, + NULL +}; + +const struct pmc_bit_map cnp_ltr_show_map[] = { + {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, + {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, + {"SATA", CNP_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, + {"XHCI", CNP_PMC_LTR_XHCI}, + {"Reserved", CNP_PMC_LTR_RESERVED}, + {"ME", CNP_PMC_LTR_ME}, + /* EVA is Enterprise Value Add, doesn't really exist on PCH */ + {"EVA", CNP_PMC_LTR_EVA}, + {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, + {"HD_AUDIO", CNP_PMC_LTR_AZ}, + {"CNV", CNP_PMC_LTR_CNV}, + {"LPSS", CNP_PMC_LTR_LPSS}, + {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, + {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, + {"CAMERA", CNP_PMC_LTR_CAM}, + {"ESPI", CNP_PMC_LTR_ESPI}, + {"SCC", CNP_PMC_LTR_SCC}, + {"ISH", CNP_PMC_LTR_ISH}, + {"UFSX2", CNP_PMC_LTR_UFSX2}, + {"EMMC", CNP_PMC_LTR_EMMC}, + /* + * Check intel_pmc_core_ids[] users of cnp_reg_map for + * a list of core SoCs using this. + */ + {"WIGIG", ICL_PMC_LTR_WIGIG}, + {"THC0", TGL_PMC_LTR_THC0}, + {"THC1", TGL_PMC_LTR_THC1}, + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, + {} +}; + +const struct pmc_reg_map cnp_reg_map = { + .pfear_sts = ext_cnp_pfear_map, + .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, + .slp_s0_res_counter_step = SPT_PMC_SLP_S0_RES_COUNTER_STEP, + .slps0_dbg_maps = cnp_slps0_dbg_maps, + .ltr_show_sts = cnp_ltr_show_map, + .msr_sts = msr_map, + .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .regmap_length = CNP_PMC_MMIO_REG_LEN, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, + .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, + .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, + .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, + .etr3_offset = ETR3_OFFSET, +}; + +void cnp_core_init(struct pmc_dev *pmcdev) +{ + pmcdev->map = &cnp_reg_map; +} diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index 17ec5825d13d..f1d802f6ec3f 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -11,7 +11,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <linux/acpi.h> #include <linux/bitfield.h> #include <linux/debugfs.h> #include <linux/delay.h> @@ -19,13 +18,9 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/suspend.h> -#include <linux/uaccess.h> -#include <linux/uuid.h> -#include <acpi/acpi_bus.h> #include <asm/cpu_device_id.h> #include <asm/intel-family.h> #include <asm/msr.h> @@ -33,11 +28,21 @@ #include "core.h" -#define ACPI_S0IX_DSM_UUID "57a6512e-3979-4e9d-9708-ff13b2508972" -#define ACPI_GET_LOW_MODE_REGISTERS 1 +/* Maximum number of modes supported by platfoms that has low power mode capability */ +const char *pmc_lpm_modes[] = { + "S0i2.0", + "S0i2.1", + "S0i2.2", + "S0i3.0", + "S0i3.1", + "S0i3.2", + "S0i3.3", + "S0i3.4", + NULL +}; /* PKGC MSRs are common across Intel Core SoCs */ -static const struct pmc_bit_map msr_map[] = { +const struct pmc_bit_map msr_map[] = { {"Package C2", MSR_PKG_C2_RESIDENCY}, {"Package C3", MSR_PKG_C3_RESIDENCY}, {"Package C6", MSR_PKG_C6_RESIDENCY}, @@ -48,903 +53,6 @@ static const struct pmc_bit_map msr_map[] = { {} }; -static const struct pmc_bit_map spt_pll_map[] = { - {"MIPI PLL", SPT_PMC_BIT_MPHY_CMN_LANE0}, - {"GEN2 USB2PCIE2 PLL", SPT_PMC_BIT_MPHY_CMN_LANE1}, - {"DMIPCIE3 PLL", SPT_PMC_BIT_MPHY_CMN_LANE2}, - {"SATA PLL", SPT_PMC_BIT_MPHY_CMN_LANE3}, - {} -}; - -static const struct pmc_bit_map spt_mphy_map[] = { - {"MPHY CORE LANE 0", SPT_PMC_BIT_MPHY_LANE0}, - {"MPHY CORE LANE 1", SPT_PMC_BIT_MPHY_LANE1}, - {"MPHY CORE LANE 2", SPT_PMC_BIT_MPHY_LANE2}, - {"MPHY CORE LANE 3", SPT_PMC_BIT_MPHY_LANE3}, - {"MPHY CORE LANE 4", SPT_PMC_BIT_MPHY_LANE4}, - {"MPHY CORE LANE 5", SPT_PMC_BIT_MPHY_LANE5}, - {"MPHY CORE LANE 6", SPT_PMC_BIT_MPHY_LANE6}, - {"MPHY CORE LANE 7", SPT_PMC_BIT_MPHY_LANE7}, - {"MPHY CORE LANE 8", SPT_PMC_BIT_MPHY_LANE8}, - {"MPHY CORE LANE 9", SPT_PMC_BIT_MPHY_LANE9}, - {"MPHY CORE LANE 10", SPT_PMC_BIT_MPHY_LANE10}, - {"MPHY CORE LANE 11", SPT_PMC_BIT_MPHY_LANE11}, - {"MPHY CORE LANE 12", SPT_PMC_BIT_MPHY_LANE12}, - {"MPHY CORE LANE 13", SPT_PMC_BIT_MPHY_LANE13}, - {"MPHY CORE LANE 14", SPT_PMC_BIT_MPHY_LANE14}, - {"MPHY CORE LANE 15", SPT_PMC_BIT_MPHY_LANE15}, - {} -}; - -static const struct pmc_bit_map spt_pfear_map[] = { - {"PMC", SPT_PMC_BIT_PMC}, - {"OPI-DMI", SPT_PMC_BIT_OPI}, - {"SPI / eSPI", SPT_PMC_BIT_SPI}, - {"XHCI", SPT_PMC_BIT_XHCI}, - {"SPA", SPT_PMC_BIT_SPA}, - {"SPB", SPT_PMC_BIT_SPB}, - {"SPC", SPT_PMC_BIT_SPC}, - {"GBE", SPT_PMC_BIT_GBE}, - {"SATA", SPT_PMC_BIT_SATA}, - {"HDA-PGD0", SPT_PMC_BIT_HDA_PGD0}, - {"HDA-PGD1", SPT_PMC_BIT_HDA_PGD1}, - {"HDA-PGD2", SPT_PMC_BIT_HDA_PGD2}, - {"HDA-PGD3", SPT_PMC_BIT_HDA_PGD3}, - {"RSVD", SPT_PMC_BIT_RSVD_0B}, - {"LPSS", SPT_PMC_BIT_LPSS}, - {"LPC", SPT_PMC_BIT_LPC}, - {"SMB", SPT_PMC_BIT_SMB}, - {"ISH", SPT_PMC_BIT_ISH}, - {"P2SB", SPT_PMC_BIT_P2SB}, - {"DFX", SPT_PMC_BIT_DFX}, - {"SCC", SPT_PMC_BIT_SCC}, - {"RSVD", SPT_PMC_BIT_RSVD_0C}, - {"FUSE", SPT_PMC_BIT_FUSE}, - {"CAMERA", SPT_PMC_BIT_CAMREA}, - {"RSVD", SPT_PMC_BIT_RSVD_0D}, - {"USB3-OTG", SPT_PMC_BIT_USB3_OTG}, - {"EXI", SPT_PMC_BIT_EXI}, - {"CSE", SPT_PMC_BIT_CSE}, - {"CSME_KVM", SPT_PMC_BIT_CSME_KVM}, - {"CSME_PMT", SPT_PMC_BIT_CSME_PMT}, - {"CSME_CLINK", SPT_PMC_BIT_CSME_CLINK}, - {"CSME_PTIO", SPT_PMC_BIT_CSME_PTIO}, - {"CSME_USBR", SPT_PMC_BIT_CSME_USBR}, - {"CSME_SUSRAM", SPT_PMC_BIT_CSME_SUSRAM}, - {"CSME_SMT", SPT_PMC_BIT_CSME_SMT}, - {"RSVD", SPT_PMC_BIT_RSVD_1A}, - {"CSME_SMS2", SPT_PMC_BIT_CSME_SMS2}, - {"CSME_SMS1", SPT_PMC_BIT_CSME_SMS1}, - {"CSME_RTC", SPT_PMC_BIT_CSME_RTC}, - {"CSME_PSF", SPT_PMC_BIT_CSME_PSF}, - {} -}; - -static const struct pmc_bit_map *ext_spt_pfear_map[] = { - /* - * Check intel_pmc_core_ids[] users of spt_reg_map for - * a list of core SoCs using this. - */ - spt_pfear_map, - NULL -}; - -static const struct pmc_bit_map spt_ltr_show_map[] = { - {"SOUTHPORT_A", SPT_PMC_LTR_SPA}, - {"SOUTHPORT_B", SPT_PMC_LTR_SPB}, - {"SATA", SPT_PMC_LTR_SATA}, - {"GIGABIT_ETHERNET", SPT_PMC_LTR_GBE}, - {"XHCI", SPT_PMC_LTR_XHCI}, - {"Reserved", SPT_PMC_LTR_RESERVED}, - {"ME", SPT_PMC_LTR_ME}, - /* EVA is Enterprise Value Add, doesn't really exist on PCH */ - {"EVA", SPT_PMC_LTR_EVA}, - {"SOUTHPORT_C", SPT_PMC_LTR_SPC}, - {"HD_AUDIO", SPT_PMC_LTR_AZ}, - {"LPSS", SPT_PMC_LTR_LPSS}, - {"SOUTHPORT_D", SPT_PMC_LTR_SPD}, - {"SOUTHPORT_E", SPT_PMC_LTR_SPE}, - {"CAMERA", SPT_PMC_LTR_CAM}, - {"ESPI", SPT_PMC_LTR_ESPI}, - {"SCC", SPT_PMC_LTR_SCC}, - {"ISH", SPT_PMC_LTR_ISH}, - /* Below two cannot be used for LTR_IGNORE */ - {"CURRENT_PLATFORM", SPT_PMC_LTR_CUR_PLT}, - {"AGGREGATED_SYSTEM", SPT_PMC_LTR_CUR_ASLT}, - {} -}; - -static const struct pmc_reg_map spt_reg_map = { - .pfear_sts = ext_spt_pfear_map, - .mphy_sts = spt_mphy_map, - .pll_sts = spt_pll_map, - .ltr_show_sts = spt_ltr_show_map, - .msr_sts = msr_map, - .slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET, - .slp_s0_res_counter_step = SPT_PMC_SLP_S0_RES_COUNTER_STEP, - .ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET, - .regmap_length = SPT_PMC_MMIO_REG_LEN, - .ppfear0_offset = SPT_PMC_XRAM_PPFEAR0A, - .ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES, - .pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET, - .pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT, - .ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED, - .pm_vric1_offset = SPT_PMC_VRIC1_OFFSET, -}; - -/* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */ -static const struct pmc_bit_map cnp_pfear_map[] = { - {"PMC", BIT(0)}, - {"OPI-DMI", BIT(1)}, - {"SPI/eSPI", BIT(2)}, - {"XHCI", BIT(3)}, - {"SPA", BIT(4)}, - {"SPB", BIT(5)}, - {"SPC", BIT(6)}, - {"GBE", BIT(7)}, - - {"SATA", BIT(0)}, - {"HDA_PGD0", BIT(1)}, - {"HDA_PGD1", BIT(2)}, - {"HDA_PGD2", BIT(3)}, - {"HDA_PGD3", BIT(4)}, - {"SPD", BIT(5)}, - {"LPSS", BIT(6)}, - {"LPC", BIT(7)}, - - {"SMB", BIT(0)}, - {"ISH", BIT(1)}, - {"P2SB", BIT(2)}, - {"NPK_VNN", BIT(3)}, - {"SDX", BIT(4)}, - {"SPE", BIT(5)}, - {"Fuse", BIT(6)}, - {"SBR8", BIT(7)}, - - {"CSME_FSC", BIT(0)}, - {"USB3_OTG", BIT(1)}, - {"EXI", BIT(2)}, - {"CSE", BIT(3)}, - {"CSME_KVM", BIT(4)}, - {"CSME_PMT", BIT(5)}, - {"CSME_CLINK", BIT(6)}, - {"CSME_PTIO", BIT(7)}, - - {"CSME_USBR", BIT(0)}, - {"CSME_SUSRAM", BIT(1)}, - {"CSME_SMT1", BIT(2)}, - {"CSME_SMT4", BIT(3)}, - {"CSME_SMS2", BIT(4)}, - {"CSME_SMS1", BIT(5)}, - {"CSME_RTC", BIT(6)}, - {"CSME_PSF", BIT(7)}, - - {"SBR0", BIT(0)}, - {"SBR1", BIT(1)}, - {"SBR2", BIT(2)}, - {"SBR3", BIT(3)}, - {"SBR4", BIT(4)}, - {"SBR5", BIT(5)}, - {"CSME_PECI", BIT(6)}, - {"PSF1", BIT(7)}, - - {"PSF2", BIT(0)}, - {"PSF3", BIT(1)}, - {"PSF4", BIT(2)}, - {"CNVI", BIT(3)}, - {"UFS0", BIT(4)}, - {"EMMC", BIT(5)}, - {"SPF", BIT(6)}, - {"SBR6", BIT(7)}, - - {"SBR7", BIT(0)}, - {"NPK_AON", BIT(1)}, - {"HDA_PGD4", BIT(2)}, - {"HDA_PGD5", BIT(3)}, - {"HDA_PGD6", BIT(4)}, - {"PSF6", BIT(5)}, - {"PSF7", BIT(6)}, - {"PSF8", BIT(7)}, - {} -}; - -static const struct pmc_bit_map *ext_cnp_pfear_map[] = { - /* - * Check intel_pmc_core_ids[] users of cnp_reg_map for - * a list of core SoCs using this. - */ - cnp_pfear_map, - NULL -}; - -static const struct pmc_bit_map icl_pfear_map[] = { - {"RES_65", BIT(0)}, - {"RES_66", BIT(1)}, - {"RES_67", BIT(2)}, - {"TAM", BIT(3)}, - {"GBETSN", BIT(4)}, - {"TBTLSX", BIT(5)}, - {"RES_71", BIT(6)}, - {"RES_72", BIT(7)}, - {} -}; - -static const struct pmc_bit_map *ext_icl_pfear_map[] = { - /* - * Check intel_pmc_core_ids[] users of icl_reg_map for - * a list of core SoCs using this. - */ - cnp_pfear_map, - icl_pfear_map, - NULL -}; - -static const struct pmc_bit_map tgl_pfear_map[] = { - {"PSF9", BIT(0)}, - {"RES_66", BIT(1)}, - {"RES_67", BIT(2)}, - {"RES_68", BIT(3)}, - {"RES_69", BIT(4)}, - {"RES_70", BIT(5)}, - {"TBTLSX", BIT(6)}, - {} -}; - -static const struct pmc_bit_map *ext_tgl_pfear_map[] = { - /* - * Check intel_pmc_core_ids[] users of tgl_reg_map for - * a list of core SoCs using this. - */ - cnp_pfear_map, - tgl_pfear_map, - NULL -}; - -static const struct pmc_bit_map cnp_slps0_dbg0_map[] = { - {"AUDIO_D3", BIT(0)}, - {"OTG_D3", BIT(1)}, - {"XHCI_D3", BIT(2)}, - {"LPIO_D3", BIT(3)}, - {"SDX_D3", BIT(4)}, - {"SATA_D3", BIT(5)}, - {"UFS0_D3", BIT(6)}, - {"UFS1_D3", BIT(7)}, - {"EMMC_D3", BIT(8)}, - {} -}; - -static const struct pmc_bit_map cnp_slps0_dbg1_map[] = { - {"SDIO_PLL_OFF", BIT(0)}, - {"USB2_PLL_OFF", BIT(1)}, - {"AUDIO_PLL_OFF", BIT(2)}, - {"OC_PLL_OFF", BIT(3)}, - {"MAIN_PLL_OFF", BIT(4)}, - {"XOSC_OFF", BIT(5)}, - {"LPC_CLKS_GATED", BIT(6)}, - {"PCIE_CLKREQS_IDLE", BIT(7)}, - {"AUDIO_ROSC_OFF", BIT(8)}, - {"HPET_XOSC_CLK_REQ", BIT(9)}, - {"PMC_ROSC_SLOW_CLK", BIT(10)}, - {"AON2_ROSC_GATED", BIT(11)}, - {"CLKACKS_DEASSERTED", BIT(12)}, - {} -}; - -static const struct pmc_bit_map cnp_slps0_dbg2_map[] = { - {"MPHY_CORE_GATED", BIT(0)}, - {"CSME_GATED", BIT(1)}, - {"USB2_SUS_GATED", BIT(2)}, - {"DYN_FLEX_IO_IDLE", BIT(3)}, - {"GBE_NO_LINK", BIT(4)}, - {"THERM_SEN_DISABLED", BIT(5)}, - {"PCIE_LOW_POWER", BIT(6)}, - {"ISH_VNNAON_REQ_ACT", BIT(7)}, - {"ISH_VNN_REQ_ACT", BIT(8)}, - {"CNV_VNNAON_REQ_ACT", BIT(9)}, - {"CNV_VNN_REQ_ACT", BIT(10)}, - {"NPK_VNNON_REQ_ACT", BIT(11)}, - {"PMSYNC_STATE_IDLE", BIT(12)}, - {"ALST_GT_THRES", BIT(13)}, - {"PMC_ARC_PG_READY", BIT(14)}, - {} -}; - -static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = { - cnp_slps0_dbg0_map, - cnp_slps0_dbg1_map, - cnp_slps0_dbg2_map, - NULL -}; - -static const struct pmc_bit_map cnp_ltr_show_map[] = { - {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, - {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, - {"SATA", CNP_PMC_LTR_SATA}, - {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, - {"XHCI", CNP_PMC_LTR_XHCI}, - {"Reserved", CNP_PMC_LTR_RESERVED}, - {"ME", CNP_PMC_LTR_ME}, - /* EVA is Enterprise Value Add, doesn't really exist on PCH */ - {"EVA", CNP_PMC_LTR_EVA}, - {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, - {"HD_AUDIO", CNP_PMC_LTR_AZ}, - {"CNV", CNP_PMC_LTR_CNV}, - {"LPSS", CNP_PMC_LTR_LPSS}, - {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, - {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, - {"CAMERA", CNP_PMC_LTR_CAM}, - {"ESPI", CNP_PMC_LTR_ESPI}, - {"SCC", CNP_PMC_LTR_SCC}, - {"ISH", CNP_PMC_LTR_ISH}, - {"UFSX2", CNP_PMC_LTR_UFSX2}, - {"EMMC", CNP_PMC_LTR_EMMC}, - /* - * Check intel_pmc_core_ids[] users of cnp_reg_map for - * a list of core SoCs using this. - */ - {"WIGIG", ICL_PMC_LTR_WIGIG}, - {"THC0", TGL_PMC_LTR_THC0}, - {"THC1", TGL_PMC_LTR_THC1}, - /* Below two cannot be used for LTR_IGNORE */ - {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, - {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, - {} -}; - -static const struct pmc_reg_map cnp_reg_map = { - .pfear_sts = ext_cnp_pfear_map, - .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, - .slp_s0_res_counter_step = SPT_PMC_SLP_S0_RES_COUNTER_STEP, - .slps0_dbg_maps = cnp_slps0_dbg_maps, - .ltr_show_sts = cnp_ltr_show_map, - .msr_sts = msr_map, - .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, - .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, - .regmap_length = CNP_PMC_MMIO_REG_LEN, - .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, - .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, - .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, - .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, - .etr3_offset = ETR3_OFFSET, -}; - -static const struct pmc_reg_map icl_reg_map = { - .pfear_sts = ext_icl_pfear_map, - .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, - .slp_s0_res_counter_step = ICL_PMC_SLP_S0_RES_COUNTER_STEP, - .slps0_dbg_maps = cnp_slps0_dbg_maps, - .ltr_show_sts = cnp_ltr_show_map, - .msr_sts = msr_map, - .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, - .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, - .regmap_length = CNP_PMC_MMIO_REG_LEN, - .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, - .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, - .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, - .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED, - .etr3_offset = ETR3_OFFSET, -}; - -static const struct pmc_bit_map tgl_clocksource_status_map[] = { - {"USB2PLL_OFF_STS", BIT(18)}, - {"PCIe/USB3.1_Gen2PLL_OFF_STS", BIT(19)}, - {"PCIe_Gen3PLL_OFF_STS", BIT(20)}, - {"OPIOPLL_OFF_STS", BIT(21)}, - {"OCPLL_OFF_STS", BIT(22)}, - {"MainPLL_OFF_STS", BIT(23)}, - {"MIPIPLL_OFF_STS", BIT(24)}, - {"Fast_XTAL_Osc_OFF_STS", BIT(25)}, - {"AC_Ring_Osc_OFF_STS", BIT(26)}, - {"MC_Ring_Osc_OFF_STS", BIT(27)}, - {"SATAPLL_OFF_STS", BIT(29)}, - {"XTAL_USB2PLL_OFF_STS", BIT(31)}, - {} -}; - -static const struct pmc_bit_map tgl_power_gating_status_map[] = { - {"CSME_PG_STS", BIT(0)}, - {"SATA_PG_STS", BIT(1)}, - {"xHCI_PG_STS", BIT(2)}, - {"UFSX2_PG_STS", BIT(3)}, - {"OTG_PG_STS", BIT(5)}, - {"SPA_PG_STS", BIT(6)}, - {"SPB_PG_STS", BIT(7)}, - {"SPC_PG_STS", BIT(8)}, - {"SPD_PG_STS", BIT(9)}, - {"SPE_PG_STS", BIT(10)}, - {"SPF_PG_STS", BIT(11)}, - {"LSX_PG_STS", BIT(13)}, - {"P2SB_PG_STS", BIT(14)}, - {"PSF_PG_STS", BIT(15)}, - {"SBR_PG_STS", BIT(16)}, - {"OPIDMI_PG_STS", BIT(17)}, - {"THC0_PG_STS", BIT(18)}, - {"THC1_PG_STS", BIT(19)}, - {"GBETSN_PG_STS", BIT(20)}, - {"GBE_PG_STS", BIT(21)}, - {"LPSS_PG_STS", BIT(22)}, - {"MMP_UFSX2_PG_STS", BIT(23)}, - {"MMP_UFSX2B_PG_STS", BIT(24)}, - {"FIA_PG_STS", BIT(25)}, - {} -}; - -static const struct pmc_bit_map tgl_d3_status_map[] = { - {"ADSP_D3_STS", BIT(0)}, - {"SATA_D3_STS", BIT(1)}, - {"xHCI0_D3_STS", BIT(2)}, - {"xDCI1_D3_STS", BIT(5)}, - {"SDX_D3_STS", BIT(6)}, - {"EMMC_D3_STS", BIT(7)}, - {"IS_D3_STS", BIT(8)}, - {"THC0_D3_STS", BIT(9)}, - {"THC1_D3_STS", BIT(10)}, - {"GBE_D3_STS", BIT(11)}, - {"GBE_TSN_D3_STS", BIT(12)}, - {} -}; - -static const struct pmc_bit_map tgl_vnn_req_status_map[] = { - {"GPIO_COM0_VNN_REQ_STS", BIT(1)}, - {"GPIO_COM1_VNN_REQ_STS", BIT(2)}, - {"GPIO_COM2_VNN_REQ_STS", BIT(3)}, - {"GPIO_COM3_VNN_REQ_STS", BIT(4)}, - {"GPIO_COM4_VNN_REQ_STS", BIT(5)}, - {"GPIO_COM5_VNN_REQ_STS", BIT(6)}, - {"Audio_VNN_REQ_STS", BIT(7)}, - {"ISH_VNN_REQ_STS", BIT(8)}, - {"CNVI_VNN_REQ_STS", BIT(9)}, - {"eSPI_VNN_REQ_STS", BIT(10)}, - {"Display_VNN_REQ_STS", BIT(11)}, - {"DTS_VNN_REQ_STS", BIT(12)}, - {"SMBUS_VNN_REQ_STS", BIT(14)}, - {"CSME_VNN_REQ_STS", BIT(15)}, - {"SMLINK0_VNN_REQ_STS", BIT(16)}, - {"SMLINK1_VNN_REQ_STS", BIT(17)}, - {"CLINK_VNN_REQ_STS", BIT(20)}, - {"DCI_VNN_REQ_STS", BIT(21)}, - {"ITH_VNN_REQ_STS", BIT(22)}, - {"CSME_VNN_REQ_STS", BIT(24)}, - {"GBE_VNN_REQ_STS", BIT(25)}, - {} -}; - -static const struct pmc_bit_map tgl_vnn_misc_status_map[] = { - {"CPU_C10_REQ_STS_0", BIT(0)}, - {"PCIe_LPM_En_REQ_STS_3", BIT(3)}, - {"ITH_REQ_STS_5", BIT(5)}, - {"CNVI_REQ_STS_6", BIT(6)}, - {"ISH_REQ_STS_7", BIT(7)}, - {"USB2_SUS_PG_Sys_REQ_STS_10", BIT(10)}, - {"PCIe_Clk_REQ_STS_12", BIT(12)}, - {"MPHY_Core_DL_REQ_STS_16", BIT(16)}, - {"Break-even_En_REQ_STS_17", BIT(17)}, - {"Auto-demo_En_REQ_STS_18", BIT(18)}, - {"MPHY_SUS_REQ_STS_22", BIT(22)}, - {"xDCI_attached_REQ_STS_24", BIT(24)}, - {} -}; - -static const struct pmc_bit_map tgl_signal_status_map[] = { - {"LSX_Wake0_En_STS", BIT(0)}, - {"LSX_Wake0_Pol_STS", BIT(1)}, - {"LSX_Wake1_En_STS", BIT(2)}, - {"LSX_Wake1_Pol_STS", BIT(3)}, - {"LSX_Wake2_En_STS", BIT(4)}, - {"LSX_Wake2_Pol_STS", BIT(5)}, - {"LSX_Wake3_En_STS", BIT(6)}, - {"LSX_Wake3_Pol_STS", BIT(7)}, - {"LSX_Wake4_En_STS", BIT(8)}, - {"LSX_Wake4_Pol_STS", BIT(9)}, - {"LSX_Wake5_En_STS", BIT(10)}, - {"LSX_Wake5_Pol_STS", BIT(11)}, - {"LSX_Wake6_En_STS", BIT(12)}, - {"LSX_Wake6_Pol_STS", BIT(13)}, - {"LSX_Wake7_En_STS", BIT(14)}, - {"LSX_Wake7_Pol_STS", BIT(15)}, - {"Intel_Se_IO_Wake0_En_STS", BIT(16)}, - {"Intel_Se_IO_Wake0_Pol_STS", BIT(17)}, - {"Intel_Se_IO_Wake1_En_STS", BIT(18)}, - {"Intel_Se_IO_Wake1_Pol_STS", BIT(19)}, - {"Int_Timer_SS_Wake0_En_STS", BIT(20)}, - {"Int_Timer_SS_Wake0_Pol_STS", BIT(21)}, - {"Int_Timer_SS_Wake1_En_STS", BIT(22)}, - {"Int_Timer_SS_Wake1_Pol_STS", BIT(23)}, - {"Int_Timer_SS_Wake2_En_STS", BIT(24)}, - {"Int_Timer_SS_Wake2_Pol_STS", BIT(25)}, - {"Int_Timer_SS_Wake3_En_STS", BIT(26)}, - {"Int_Timer_SS_Wake3_Pol_STS", BIT(27)}, - {"Int_Timer_SS_Wake4_En_STS", BIT(28)}, - {"Int_Timer_SS_Wake4_Pol_STS", BIT(29)}, - {"Int_Timer_SS_Wake5_En_STS", BIT(30)}, - {"Int_Timer_SS_Wake5_Pol_STS", BIT(31)}, - {} -}; - -static const struct pmc_bit_map *tgl_lpm_maps[] = { - tgl_clocksource_status_map, - tgl_power_gating_status_map, - tgl_d3_status_map, - tgl_vnn_req_status_map, - tgl_vnn_misc_status_map, - tgl_signal_status_map, - NULL -}; - -static const struct pmc_reg_map tgl_reg_map = { - .pfear_sts = ext_tgl_pfear_map, - .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, - .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, - .ltr_show_sts = cnp_ltr_show_map, - .msr_sts = msr_map, - .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, - .regmap_length = CNP_PMC_MMIO_REG_LEN, - .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, - .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, - .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, - .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED, - .lpm_num_maps = TGL_LPM_NUM_MAPS, - .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, - .lpm_sts_latch_en_offset = TGL_LPM_STS_LATCH_EN_OFFSET, - .lpm_en_offset = TGL_LPM_EN_OFFSET, - .lpm_priority_offset = TGL_LPM_PRI_OFFSET, - .lpm_residency_offset = TGL_LPM_RESIDENCY_OFFSET, - .lpm_sts = tgl_lpm_maps, - .lpm_status_offset = TGL_LPM_STATUS_OFFSET, - .lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET, - .etr3_offset = ETR3_OFFSET, -}; - -static void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev) -{ - struct pmc_dev *pmcdev = platform_get_drvdata(pdev); - const int num_maps = pmcdev->map->lpm_num_maps; - u32 lpm_size = LPM_MAX_NUM_MODES * num_maps * 4; - union acpi_object *out_obj; - struct acpi_device *adev; - guid_t s0ix_dsm_guid; - u32 *lpm_req_regs, *addr; - - adev = ACPI_COMPANION(&pdev->dev); - if (!adev) - return; - - guid_parse(ACPI_S0IX_DSM_UUID, &s0ix_dsm_guid); - - out_obj = acpi_evaluate_dsm(adev->handle, &s0ix_dsm_guid, 0, - ACPI_GET_LOW_MODE_REGISTERS, NULL); - if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { - u32 size = out_obj->buffer.length; - - if (size != lpm_size) { - acpi_handle_debug(adev->handle, - "_DSM returned unexpected buffer size, have %u, expect %u\n", - size, lpm_size); - goto free_acpi_obj; - } - } else { - acpi_handle_debug(adev->handle, - "_DSM function 0 evaluation failed\n"); - goto free_acpi_obj; - } - - addr = (u32 *)out_obj->buffer.pointer; - - lpm_req_regs = devm_kzalloc(&pdev->dev, lpm_size * sizeof(u32), - GFP_KERNEL); - if (!lpm_req_regs) - goto free_acpi_obj; - - memcpy(lpm_req_regs, addr, lpm_size); - pmcdev->lpm_req_regs = lpm_req_regs; - -free_acpi_obj: - ACPI_FREE(out_obj); -} - -/* Alder Lake: PGD PFET Enable Ack Status Register(s) bitmap */ -static const struct pmc_bit_map adl_pfear_map[] = { - {"SPI/eSPI", BIT(2)}, - {"XHCI", BIT(3)}, - {"SPA", BIT(4)}, - {"SPB", BIT(5)}, - {"SPC", BIT(6)}, - {"GBE", BIT(7)}, - - {"SATA", BIT(0)}, - {"HDA_PGD0", BIT(1)}, - {"HDA_PGD1", BIT(2)}, - {"HDA_PGD2", BIT(3)}, - {"HDA_PGD3", BIT(4)}, - {"SPD", BIT(5)}, - {"LPSS", BIT(6)}, - - {"SMB", BIT(0)}, - {"ISH", BIT(1)}, - {"ITH", BIT(3)}, - - {"XDCI", BIT(1)}, - {"DCI", BIT(2)}, - {"CSE", BIT(3)}, - {"CSME_KVM", BIT(4)}, - {"CSME_PMT", BIT(5)}, - {"CSME_CLINK", BIT(6)}, - {"CSME_PTIO", BIT(7)}, - - {"CSME_USBR", BIT(0)}, - {"CSME_SUSRAM", BIT(1)}, - {"CSME_SMT1", BIT(2)}, - {"CSME_SMS2", BIT(4)}, - {"CSME_SMS1", BIT(5)}, - {"CSME_RTC", BIT(6)}, - {"CSME_PSF", BIT(7)}, - - {"CNVI", BIT(3)}, - - {"HDA_PGD4", BIT(2)}, - {"HDA_PGD5", BIT(3)}, - {"HDA_PGD6", BIT(4)}, - {} -}; - -static const struct pmc_bit_map *ext_adl_pfear_map[] = { - /* - * Check intel_pmc_core_ids[] users of cnp_reg_map for - * a list of core SoCs using this. - */ - adl_pfear_map, - NULL -}; - -static const struct pmc_bit_map adl_ltr_show_map[] = { - {"SOUTHPORT_A", CNP_PMC_LTR_SPA}, - {"SOUTHPORT_B", CNP_PMC_LTR_SPB}, - {"SATA", CNP_PMC_LTR_SATA}, - {"GIGABIT_ETHERNET", CNP_PMC_LTR_GBE}, - {"XHCI", CNP_PMC_LTR_XHCI}, - {"SOUTHPORT_F", ADL_PMC_LTR_SPF}, - {"ME", CNP_PMC_LTR_ME}, - /* EVA is Enterprise Value Add, doesn't really exist on PCH */ - {"SATA1", CNP_PMC_LTR_EVA}, - {"SOUTHPORT_C", CNP_PMC_LTR_SPC}, - {"HD_AUDIO", CNP_PMC_LTR_AZ}, - {"CNV", CNP_PMC_LTR_CNV}, - {"LPSS", CNP_PMC_LTR_LPSS}, - {"SOUTHPORT_D", CNP_PMC_LTR_SPD}, - {"SOUTHPORT_E", CNP_PMC_LTR_SPE}, - {"SATA2", CNP_PMC_LTR_CAM}, - {"ESPI", CNP_PMC_LTR_ESPI}, - {"SCC", CNP_PMC_LTR_SCC}, - {"ISH", CNP_PMC_LTR_ISH}, - {"UFSX2", CNP_PMC_LTR_UFSX2}, - {"EMMC", CNP_PMC_LTR_EMMC}, - /* - * Check intel_pmc_core_ids[] users of cnp_reg_map for - * a list of core SoCs using this. - */ - {"WIGIG", ICL_PMC_LTR_WIGIG}, - {"THC0", TGL_PMC_LTR_THC0}, - {"THC1", TGL_PMC_LTR_THC1}, - {"SOUTHPORT_G", CNP_PMC_LTR_RESERVED}, - - /* Below two cannot be used for LTR_IGNORE */ - {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, - {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, - {} -}; - -static const struct pmc_bit_map adl_clocksource_status_map[] = { - {"CLKPART1_OFF_STS", BIT(0)}, - {"CLKPART2_OFF_STS", BIT(1)}, - {"CLKPART3_OFF_STS", BIT(2)}, - {"CLKPART4_OFF_STS", BIT(3)}, - {"CLKPART5_OFF_STS", BIT(4)}, - {"CLKPART6_OFF_STS", BIT(5)}, - {"CLKPART7_OFF_STS", BIT(6)}, - {"CLKPART8_OFF_STS", BIT(7)}, - {"PCIE0PLL_OFF_STS", BIT(10)}, - {"PCIE1PLL_OFF_STS", BIT(11)}, - {"PCIE2PLL_OFF_STS", BIT(12)}, - {"PCIE3PLL_OFF_STS", BIT(13)}, - {"PCIE4PLL_OFF_STS", BIT(14)}, - {"PCIE5PLL_OFF_STS", BIT(15)}, - {"PCIE6PLL_OFF_STS", BIT(16)}, - {"USB2PLL_OFF_STS", BIT(18)}, - {"OCPLL_OFF_STS", BIT(22)}, - {"AUDIOPLL_OFF_STS", BIT(23)}, - {"GBEPLL_OFF_STS", BIT(24)}, - {"Fast_XTAL_Osc_OFF_STS", BIT(25)}, - {"AC_Ring_Osc_OFF_STS", BIT(26)}, - {"MC_Ring_Osc_OFF_STS", BIT(27)}, - {"SATAPLL_OFF_STS", BIT(29)}, - {"USB3PLL_OFF_STS", BIT(31)}, - {} -}; - -static const struct pmc_bit_map adl_power_gating_status_0_map[] = { - {"PMC_PGD0_PG_STS", BIT(0)}, - {"DMI_PGD0_PG_STS", BIT(1)}, - {"ESPISPI_PGD0_PG_STS", BIT(2)}, - {"XHCI_PGD0_PG_STS", BIT(3)}, - {"SPA_PGD0_PG_STS", BIT(4)}, - {"SPB_PGD0_PG_STS", BIT(5)}, - {"SPC_PGD0_PG_STS", BIT(6)}, - {"GBE_PGD0_PG_STS", BIT(7)}, - {"SATA_PGD0_PG_STS", BIT(8)}, - {"DSP_PGD0_PG_STS", BIT(9)}, - {"DSP_PGD1_PG_STS", BIT(10)}, - {"DSP_PGD2_PG_STS", BIT(11)}, - {"DSP_PGD3_PG_STS", BIT(12)}, - {"SPD_PGD0_PG_STS", BIT(13)}, - {"LPSS_PGD0_PG_STS", BIT(14)}, - {"SMB_PGD0_PG_STS", BIT(16)}, - {"ISH_PGD0_PG_STS", BIT(17)}, - {"NPK_PGD0_PG_STS", BIT(19)}, - {"PECI_PGD0_PG_STS", BIT(21)}, - {"XDCI_PGD0_PG_STS", BIT(25)}, - {"EXI_PGD0_PG_STS", BIT(26)}, - {"CSE_PGD0_PG_STS", BIT(27)}, - {"KVMCC_PGD0_PG_STS", BIT(28)}, - {"PMT_PGD0_PG_STS", BIT(29)}, - {"CLINK_PGD0_PG_STS", BIT(30)}, - {"PTIO_PGD0_PG_STS", BIT(31)}, - {} -}; - -static const struct pmc_bit_map adl_power_gating_status_1_map[] = { - {"USBR0_PGD0_PG_STS", BIT(0)}, - {"SMT1_PGD0_PG_STS", BIT(2)}, - {"CSMERTC_PGD0_PG_STS", BIT(6)}, - {"CSMEPSF_PGD0_PG_STS", BIT(7)}, - {"CNVI_PGD0_PG_STS", BIT(19)}, - {"DSP_PGD4_PG_STS", BIT(26)}, - {"SPG_PGD0_PG_STS", BIT(27)}, - {"SPE_PGD0_PG_STS", BIT(28)}, - {} -}; - -static const struct pmc_bit_map adl_power_gating_status_2_map[] = { - {"THC0_PGD0_PG_STS", BIT(7)}, - {"THC1_PGD0_PG_STS", BIT(8)}, - {"SPF_PGD0_PG_STS", BIT(14)}, - {} -}; - -static const struct pmc_bit_map adl_d3_status_0_map[] = { - {"ISH_D3_STS", BIT(2)}, - {"LPSS_D3_STS", BIT(3)}, - {"XDCI_D3_STS", BIT(4)}, - {"XHCI_D3_STS", BIT(5)}, - {"SPA_D3_STS", BIT(12)}, - {"SPB_D3_STS", BIT(13)}, - {"SPC_D3_STS", BIT(14)}, - {"SPD_D3_STS", BIT(15)}, - {"SPE_D3_STS", BIT(16)}, - {"DSP_D3_STS", BIT(19)}, - {"SATA_D3_STS", BIT(20)}, - {"DMI_D3_STS", BIT(22)}, - {} -}; - -static const struct pmc_bit_map adl_d3_status_1_map[] = { - {"GBE_D3_STS", BIT(19)}, - {"CNVI_D3_STS", BIT(27)}, - {} -}; - -static const struct pmc_bit_map adl_d3_status_2_map[] = { - {"CSMERTC_D3_STS", BIT(1)}, - {"CSE_D3_STS", BIT(4)}, - {"KVMCC_D3_STS", BIT(5)}, - {"USBR0_D3_STS", BIT(6)}, - {"SMT1_D3_STS", BIT(8)}, - {"PTIO_D3_STS", BIT(16)}, - {"PMT_D3_STS", BIT(17)}, - {} -}; - -static const struct pmc_bit_map adl_d3_status_3_map[] = { - {"THC0_D3_STS", BIT(14)}, - {"THC1_D3_STS", BIT(15)}, - {} -}; - -static const struct pmc_bit_map adl_vnn_req_status_0_map[] = { - {"ISH_VNN_REQ_STS", BIT(2)}, - {"ESPISPI_VNN_REQ_STS", BIT(18)}, - {"DSP_VNN_REQ_STS", BIT(19)}, - {} -}; - -static const struct pmc_bit_map adl_vnn_req_status_1_map[] = { - {"NPK_VNN_REQ_STS", BIT(4)}, - {"EXI_VNN_REQ_STS", BIT(9)}, - {"GBE_VNN_REQ_STS", BIT(19)}, - {"SMB_VNN_REQ_STS", BIT(25)}, - {"CNVI_VNN_REQ_STS", BIT(27)}, - {} -}; - -static const struct pmc_bit_map adl_vnn_req_status_2_map[] = { - {"CSMERTC_VNN_REQ_STS", BIT(1)}, - {"CSE_VNN_REQ_STS", BIT(4)}, - {"SMT1_VNN_REQ_STS", BIT(8)}, - {"CLINK_VNN_REQ_STS", BIT(14)}, - {"GPIOCOM4_VNN_REQ_STS", BIT(20)}, - {"GPIOCOM3_VNN_REQ_STS", BIT(21)}, - {"GPIOCOM2_VNN_REQ_STS", BIT(22)}, - {"GPIOCOM1_VNN_REQ_STS", BIT(23)}, - {"GPIOCOM0_VNN_REQ_STS", BIT(24)}, - {} -}; - -static const struct pmc_bit_map adl_vnn_req_status_3_map[] = { - {"GPIOCOM5_VNN_REQ_STS", BIT(11)}, - {} -}; - -static const struct pmc_bit_map adl_vnn_misc_status_map[] = { - {"CPU_C10_REQ_STS", BIT(0)}, - {"PCIe_LPM_En_REQ_STS", BIT(3)}, - {"ITH_REQ_STS", BIT(5)}, - {"CNVI_REQ_STS", BIT(6)}, - {"ISH_REQ_STS", BIT(7)}, - {"USB2_SUS_PG_Sys_REQ_STS", BIT(10)}, - {"PCIe_Clk_REQ_STS", BIT(12)}, - {"MPHY_Core_DL_REQ_STS", BIT(16)}, - {"Break-even_En_REQ_STS", BIT(17)}, - {"MPHY_SUS_REQ_STS", BIT(22)}, - {"xDCI_attached_REQ_STS", BIT(24)}, - {} -}; - -static const struct pmc_bit_map *adl_lpm_maps[] = { - adl_clocksource_status_map, - adl_power_gating_status_0_map, - adl_power_gating_status_1_map, - adl_power_gating_status_2_map, - adl_d3_status_0_map, - adl_d3_status_1_map, - adl_d3_status_2_map, - adl_d3_status_3_map, - adl_vnn_req_status_0_map, - adl_vnn_req_status_1_map, - adl_vnn_req_status_2_map, - adl_vnn_req_status_3_map, - adl_vnn_misc_status_map, - tgl_signal_status_map, - NULL -}; - -static const struct pmc_reg_map adl_reg_map = { - .pfear_sts = ext_adl_pfear_map, - .slp_s0_offset = ADL_PMC_SLP_S0_RES_COUNTER_OFFSET, - .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, - .ltr_show_sts = adl_ltr_show_map, - .msr_sts = msr_map, - .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, - .regmap_length = CNP_PMC_MMIO_REG_LEN, - .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, - .ppfear_buckets = CNP_PPFEAR_NUM_ENTRIES, - .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, - .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, - .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, - .lpm_num_modes = ADL_LPM_NUM_MODES, - .lpm_num_maps = ADL_LPM_NUM_MAPS, - .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, - .etr3_offset = ETR3_OFFSET, - .lpm_sts_latch_en_offset = ADL_LPM_STATUS_LATCH_EN_OFFSET, - .lpm_priority_offset = ADL_LPM_PRI_OFFSET, - .lpm_en_offset = ADL_LPM_EN_OFFSET, - .lpm_residency_offset = ADL_LPM_RESIDENCY_OFFSET, - .lpm_sts = adl_lpm_maps, - .lpm_status_offset = ADL_LPM_STATUS_OFFSET, - .lpm_live_status_offset = ADL_LPM_LIVE_STATUS_OFFSET, -}; - static inline u32 pmc_core_reg_read(struct pmc_dev *pmcdev, int reg_offset) { return readl(pmcdev->regbase + reg_offset); @@ -1327,7 +435,7 @@ out_unlock: } DEFINE_SHOW_ATTRIBUTE(pmc_core_pll); -static int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value) +int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value) { const struct pmc_reg_map *map = pmcdev->map; u32 reg; @@ -1793,7 +901,11 @@ static void pmc_core_get_low_power_modes(struct platform_device *pdev) return; lpm_en = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_en_offset); - pmcdev->num_lpm_modes = hweight32(lpm_en); + /* For MTL, BIT 31 is not an lpm mode but a enable bit. + * Lower byte is enough to cover the number of lpm modes for all + * platforms and hence mask the upper 3 bytes. + */ + pmcdev->num_lpm_modes = hweight32(lpm_en & 0xFF); /* Read 32 bit LPM_PRI register */ lpm_pri = pmc_core_reg_read(pmcdev, pmcdev->map->lpm_priority_offset); @@ -1896,26 +1008,27 @@ static void pmc_core_dbgfs_register(struct pmc_dev *pmcdev) } static const struct x86_cpu_id intel_pmc_core_ids[] = { - X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, &spt_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, &spt_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, &spt_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &spt_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, &cnp_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, &icl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_NNPI, &icl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, &cnp_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, &cnp_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, &tgl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, &tgl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, &tgl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, &icl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &tgl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &tgl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, &tgl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, &tgl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, &adl_reg_map), - X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, &adl_reg_map), + X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, spt_core_init), + X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, spt_core_init), + X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, spt_core_init), + X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, spt_core_init), + X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, cnp_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, icl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_NNPI, icl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, cnp_core_init), + X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, cnp_core_init), + X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, tgl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, tgl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT, tgl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, icl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, tgl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, tgl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, tgl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, adl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, tgl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, adl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, adl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, mtl_core_init), {} }; @@ -1975,6 +1088,7 @@ static int pmc_core_probe(struct platform_device *pdev) static bool device_initialized; struct pmc_dev *pmcdev; const struct x86_cpu_id *cpu_id; + void (*core_init)(struct pmc_dev *pmcdev); u64 slp_s0_addr; if (device_initialized) @@ -1985,20 +1099,25 @@ static int pmc_core_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, pmcdev); + pmcdev->pdev = pdev; cpu_id = x86_match_cpu(intel_pmc_core_ids); if (!cpu_id) return -ENODEV; - pmcdev->map = (struct pmc_reg_map *)cpu_id->driver_data; + core_init = (void (*)(struct pmc_dev *))cpu_id->driver_data; /* * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here * Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap * in this case. */ - if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids)) - pmcdev->map = &cnp_reg_map; + if (core_init == spt_core_init && !pci_dev_present(pmc_pci_ids)) + core_init = cnp_core_init; + + mutex_init(&pmcdev->lock); + core_init(pmcdev); + if (lpit_read_residency_count_address(&slp_s0_addr)) { pmcdev->base_addr = PMC_BASE_ADDR_DEFAULT; @@ -2014,24 +1133,13 @@ static int pmc_core_probe(struct platform_device *pdev) if (!pmcdev->regbase) return -ENOMEM; - mutex_init(&pmcdev->lock); + if (pmcdev->core_configure) + pmcdev->core_configure(pmcdev); pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(pmcdev); pmc_core_get_low_power_modes(pdev); pmc_core_do_dmi_quirks(pmcdev); - if (pmcdev->map == &tgl_reg_map) - pmc_core_get_tgl_lpm_reqs(pdev); - - /* - * On TGL and ADL, due to a hardware limitation, the GBE LTR blocks PC10 - * when a cable is attached. Tell the PMC to ignore it. - */ - if (pmcdev->map == &tgl_reg_map || pmcdev->map == &adl_reg_map) { - dev_dbg(&pdev->dev, "ignoring GBE LTR\n"); - pmc_core_send_ltr_ignore(pmcdev, 3); - } - pmc_core_dbgfs_register(pmcdev); device_initialized = true; diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h index 7a059e02c265..810204d758ab 100644 --- a/drivers/platform/x86/intel/pmc/core.h +++ b/drivers/platform/x86/intel/pmc/core.h @@ -12,7 +12,9 @@ #ifndef PMC_CORE_H #define PMC_CORE_H +#include <linux/acpi.h> #include <linux/bits.h> +#include <linux/platform_device.h> #define PMC_BASE_ADDR_DEFAULT 0xFE000000 @@ -236,17 +238,17 @@ enum ppfear_regs { #define ADL_LPM_STATUS_LATCH_EN_OFFSET 0x1704 #define ADL_LPM_LIVE_STATUS_OFFSET 0x1764 -static const char *pmc_lpm_modes[] = { - "S0i2.0", - "S0i2.1", - "S0i2.2", - "S0i3.0", - "S0i3.1", - "S0i3.2", - "S0i3.3", - "S0i3.4", - NULL -}; +/* Meteor Lake Power Management Controller register offsets */ +#define MTL_LPM_EN_OFFSET 0x1798 +#define MTL_LPM_RESIDENCY_OFFSET 0x17A0 + +/* Meteor Lake Low Power Mode debug registers */ +#define MTL_LPM_PRI_OFFSET 0x179C +#define MTL_LPM_STATUS_LATCH_EN_OFFSET 0x16F8 +#define MTL_LPM_STATUS_OFFSET 0x1700 +#define MTL_LPM_LIVE_STATUS_OFFSET 0x175C + +extern const char *pmc_lpm_modes[]; struct pmc_bit_map { const char *name; @@ -264,7 +266,7 @@ struct pmc_bit_map { * @slp_s0_offset: PWRMBASE offset to read SLP_S0 residency * @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit * @regmap_length: Length of memory to map from PWRMBASE address to access - * @ppfear0_offset: PWRMBASE offset to to read PPFEAR* + * @ppfear0_offset: PWRMBASE offset to read PPFEAR* * @ppfear_buckets: Number of 8 bits blocks to read all IP blocks from * PPFEAR * @pm_cfg_offset: PWRMBASE offset to PM_CFG register @@ -312,6 +314,7 @@ struct pmc_reg_map { * @regbase: pointer to io-remapped memory location * @map: pointer to pmc_reg_map struct that contains platform * specific attributes + * @pdev: pointer to platform_device struct * @dbgfs_dir: path to debugfs interface * @pmc_xram_read_bit: flag to indicate whether PMC XRAM shadow registers * used to read MPHY PG and PLL status are available @@ -322,6 +325,7 @@ struct pmc_reg_map { * @num_lpm_modes: Count of enabled modes * @lpm_en_modes: Array of enabled modes from lowest to highest priority * @lpm_req_regs: List of substate requirements + * @core_configure: Function pointer to configure the platform * * pmc_dev contains info about power management controller device. */ @@ -330,6 +334,7 @@ struct pmc_dev { void __iomem *regbase; const struct pmc_reg_map *map; struct dentry *dbgfs_dir; + struct platform_device *pdev; int pmc_xram_read_bit; struct mutex lock; /* generic mutex lock for PMC Core */ @@ -339,8 +344,70 @@ struct pmc_dev { int num_lpm_modes; int lpm_en_modes[LPM_MAX_NUM_MODES]; u32 *lpm_req_regs; + void (*core_configure)(struct pmc_dev *pmcdev); }; +extern const struct pmc_bit_map msr_map[]; +extern const struct pmc_bit_map spt_pll_map[]; +extern const struct pmc_bit_map spt_mphy_map[]; +extern const struct pmc_bit_map spt_pfear_map[]; +extern const struct pmc_bit_map *ext_spt_pfear_map[]; +extern const struct pmc_bit_map spt_ltr_show_map[]; +extern const struct pmc_reg_map spt_reg_map; +extern const struct pmc_bit_map cnp_pfear_map[]; +extern const struct pmc_bit_map *ext_cnp_pfear_map[]; +extern const struct pmc_bit_map cnp_slps0_dbg0_map[]; +extern const struct pmc_bit_map cnp_slps0_dbg1_map[]; +extern const struct pmc_bit_map cnp_slps0_dbg2_map[]; +extern const struct pmc_bit_map *cnp_slps0_dbg_maps[]; +extern const struct pmc_bit_map cnp_ltr_show_map[]; +extern const struct pmc_reg_map cnp_reg_map; +extern const struct pmc_bit_map icl_pfear_map[]; +extern const struct pmc_bit_map *ext_icl_pfear_map[]; +extern const struct pmc_reg_map icl_reg_map; +extern const struct pmc_bit_map tgl_pfear_map[]; +extern const struct pmc_bit_map *ext_tgl_pfear_map[]; +extern const struct pmc_bit_map tgl_clocksource_status_map[]; +extern const struct pmc_bit_map tgl_power_gating_status_map[]; +extern const struct pmc_bit_map tgl_d3_status_map[]; +extern const struct pmc_bit_map tgl_vnn_req_status_map[]; +extern const struct pmc_bit_map tgl_vnn_misc_status_map[]; +extern const struct pmc_bit_map tgl_signal_status_map[]; +extern const struct pmc_bit_map *tgl_lpm_maps[]; +extern const struct pmc_reg_map tgl_reg_map; +extern const struct pmc_bit_map adl_pfear_map[]; +extern const struct pmc_bit_map *ext_adl_pfear_map[]; +extern const struct pmc_bit_map adl_ltr_show_map[]; +extern const struct pmc_bit_map adl_clocksource_status_map[]; +extern const struct pmc_bit_map adl_power_gating_status_0_map[]; +extern const struct pmc_bit_map adl_power_gating_status_1_map[]; +extern const struct pmc_bit_map adl_power_gating_status_2_map[]; +extern const struct pmc_bit_map adl_d3_status_0_map[]; +extern const struct pmc_bit_map adl_d3_status_1_map[]; +extern const struct pmc_bit_map adl_d3_status_2_map[]; +extern const struct pmc_bit_map adl_d3_status_3_map[]; +extern const struct pmc_bit_map adl_vnn_req_status_0_map[]; +extern const struct pmc_bit_map adl_vnn_req_status_1_map[]; +extern const struct pmc_bit_map adl_vnn_req_status_2_map[]; +extern const struct pmc_bit_map adl_vnn_req_status_3_map[]; +extern const struct pmc_bit_map adl_vnn_misc_status_map[]; +extern const struct pmc_bit_map *adl_lpm_maps[]; +extern const struct pmc_reg_map adl_reg_map; +extern const struct pmc_reg_map mtl_reg_map; + +extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev); +extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value); + +void spt_core_init(struct pmc_dev *pmcdev); +void cnp_core_init(struct pmc_dev *pmcdev); +void icl_core_init(struct pmc_dev *pmcdev); +void tgl_core_init(struct pmc_dev *pmcdev); +void adl_core_init(struct pmc_dev *pmcdev); +void mtl_core_init(struct pmc_dev *pmcdev); +void tgl_core_configure(struct pmc_dev *pmcdev); +void adl_core_configure(struct pmc_dev *pmcdev); +void mtl_core_configure(struct pmc_dev *pmcdev); + #define pmc_for_each_mode(i, mode, pmcdev) \ for (i = 0, mode = pmcdev->lpm_en_modes[i]; \ i < pmcdev->num_lpm_modes; \ diff --git a/drivers/platform/x86/intel/pmc/icl.c b/drivers/platform/x86/intel/pmc/icl.c new file mode 100644 index 000000000000..2f11b1a6daeb --- /dev/null +++ b/drivers/platform/x86/intel/pmc/icl.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains platform specific structure definitions + * and init function used by Ice Lake PCH. + * + * Copyright (c) 2022, Intel Corporation. + * All Rights Reserved. + * + */ + +#include "core.h" + +const struct pmc_bit_map icl_pfear_map[] = { + {"RES_65", BIT(0)}, + {"RES_66", BIT(1)}, + {"RES_67", BIT(2)}, + {"TAM", BIT(3)}, + {"GBETSN", BIT(4)}, + {"TBTLSX", BIT(5)}, + {"RES_71", BIT(6)}, + {"RES_72", BIT(7)}, + {} +}; + +const struct pmc_bit_map *ext_icl_pfear_map[] = { + /* + * Check intel_pmc_core_ids[] users of icl_reg_map for + * a list of core SoCs using this. + */ + cnp_pfear_map, + icl_pfear_map, + NULL +}; + +const struct pmc_reg_map icl_reg_map = { + .pfear_sts = ext_icl_pfear_map, + .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, + .slp_s0_res_counter_step = ICL_PMC_SLP_S0_RES_COUNTER_STEP, + .slps0_dbg_maps = cnp_slps0_dbg_maps, + .ltr_show_sts = cnp_ltr_show_map, + .msr_sts = msr_map, + .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .regmap_length = CNP_PMC_MMIO_REG_LEN, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, + .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, + .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, + .ltr_ignore_max = ICL_NUM_IP_IGN_ALLOWED, + .etr3_offset = ETR3_OFFSET, +}; + +void icl_core_init(struct pmc_dev *pmcdev) +{ + pmcdev->map = &icl_reg_map; +} diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c new file mode 100644 index 000000000000..eeb3bd8c2502 --- /dev/null +++ b/drivers/platform/x86/intel/pmc/mtl.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains platform specific structure definitions + * and init function used by Meteor Lake PCH. + * + * Copyright (c) 2022, Intel Corporation. + * All Rights Reserved. + * + */ + +#include "core.h" + +const struct pmc_reg_map mtl_reg_map = { + .pfear_sts = ext_tgl_pfear_map, + .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, + .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, + .ltr_show_sts = adl_ltr_show_map, + .msr_sts = msr_map, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .regmap_length = CNP_PMC_MMIO_REG_LEN, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, + .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, + .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, + .ltr_ignore_max = ADL_NUM_IP_IGN_ALLOWED, + .lpm_num_modes = ADL_LPM_NUM_MODES, + .lpm_num_maps = ADL_LPM_NUM_MAPS, + .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, + .etr3_offset = ETR3_OFFSET, + .lpm_sts_latch_en_offset = MTL_LPM_STATUS_LATCH_EN_OFFSET, + .lpm_priority_offset = MTL_LPM_PRI_OFFSET, + .lpm_en_offset = MTL_LPM_EN_OFFSET, + .lpm_residency_offset = MTL_LPM_RESIDENCY_OFFSET, + .lpm_sts = adl_lpm_maps, + .lpm_status_offset = MTL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET, +}; + +void mtl_core_configure(struct pmc_dev *pmcdev) +{ + /* Due to a hardware limitation, the GBE LTR blocks PC10 + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); + pmc_core_send_ltr_ignore(pmcdev, 3); +} + +void mtl_core_init(struct pmc_dev *pmcdev) +{ + pmcdev->map = &mtl_reg_map; + pmcdev->core_configure = mtl_core_configure; +} diff --git a/drivers/platform/x86/intel/pmc/spt.c b/drivers/platform/x86/intel/pmc/spt.c new file mode 100644 index 000000000000..e16982236778 --- /dev/null +++ b/drivers/platform/x86/intel/pmc/spt.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains platform specific structure definitions + * and init function used by Sunrise Point PCH. + * + * Copyright (c) 2022, Intel Corporation. + * All Rights Reserved. + * + */ + +#include "core.h" + +const struct pmc_bit_map spt_pll_map[] = { + {"MIPI PLL", SPT_PMC_BIT_MPHY_CMN_LANE0}, + {"GEN2 USB2PCIE2 PLL", SPT_PMC_BIT_MPHY_CMN_LANE1}, + {"DMIPCIE3 PLL", SPT_PMC_BIT_MPHY_CMN_LANE2}, + {"SATA PLL", SPT_PMC_BIT_MPHY_CMN_LANE3}, + {} +}; + +const struct pmc_bit_map spt_mphy_map[] = { + {"MPHY CORE LANE 0", SPT_PMC_BIT_MPHY_LANE0}, + {"MPHY CORE LANE 1", SPT_PMC_BIT_MPHY_LANE1}, + {"MPHY CORE LANE 2", SPT_PMC_BIT_MPHY_LANE2}, + {"MPHY CORE LANE 3", SPT_PMC_BIT_MPHY_LANE3}, + {"MPHY CORE LANE 4", SPT_PMC_BIT_MPHY_LANE4}, + {"MPHY CORE LANE 5", SPT_PMC_BIT_MPHY_LANE5}, + {"MPHY CORE LANE 6", SPT_PMC_BIT_MPHY_LANE6}, + {"MPHY CORE LANE 7", SPT_PMC_BIT_MPHY_LANE7}, + {"MPHY CORE LANE 8", SPT_PMC_BIT_MPHY_LANE8}, + {"MPHY CORE LANE 9", SPT_PMC_BIT_MPHY_LANE9}, + {"MPHY CORE LANE 10", SPT_PMC_BIT_MPHY_LANE10}, + {"MPHY CORE LANE 11", SPT_PMC_BIT_MPHY_LANE11}, + {"MPHY CORE LANE 12", SPT_PMC_BIT_MPHY_LANE12}, + {"MPHY CORE LANE 13", SPT_PMC_BIT_MPHY_LANE13}, + {"MPHY CORE LANE 14", SPT_PMC_BIT_MPHY_LANE14}, + {"MPHY CORE LANE 15", SPT_PMC_BIT_MPHY_LANE15}, + {} +}; + +const struct pmc_bit_map spt_pfear_map[] = { + {"PMC", SPT_PMC_BIT_PMC}, + {"OPI-DMI", SPT_PMC_BIT_OPI}, + {"SPI / eSPI", SPT_PMC_BIT_SPI}, + {"XHCI", SPT_PMC_BIT_XHCI}, + {"SPA", SPT_PMC_BIT_SPA}, + {"SPB", SPT_PMC_BIT_SPB}, + {"SPC", SPT_PMC_BIT_SPC}, + {"GBE", SPT_PMC_BIT_GBE}, + {"SATA", SPT_PMC_BIT_SATA}, + {"HDA-PGD0", SPT_PMC_BIT_HDA_PGD0}, + {"HDA-PGD1", SPT_PMC_BIT_HDA_PGD1}, + {"HDA-PGD2", SPT_PMC_BIT_HDA_PGD2}, + {"HDA-PGD3", SPT_PMC_BIT_HDA_PGD3}, + {"RSVD", SPT_PMC_BIT_RSVD_0B}, + {"LPSS", SPT_PMC_BIT_LPSS}, + {"LPC", SPT_PMC_BIT_LPC}, + {"SMB", SPT_PMC_BIT_SMB}, + {"ISH", SPT_PMC_BIT_ISH}, + {"P2SB", SPT_PMC_BIT_P2SB}, + {"DFX", SPT_PMC_BIT_DFX}, + {"SCC", SPT_PMC_BIT_SCC}, + {"RSVD", SPT_PMC_BIT_RSVD_0C}, + {"FUSE", SPT_PMC_BIT_FUSE}, + {"CAMERA", SPT_PMC_BIT_CAMREA}, + {"RSVD", SPT_PMC_BIT_RSVD_0D}, + {"USB3-OTG", SPT_PMC_BIT_USB3_OTG}, + {"EXI", SPT_PMC_BIT_EXI}, + {"CSE", SPT_PMC_BIT_CSE}, + {"CSME_KVM", SPT_PMC_BIT_CSME_KVM}, + {"CSME_PMT", SPT_PMC_BIT_CSME_PMT}, + {"CSME_CLINK", SPT_PMC_BIT_CSME_CLINK}, + {"CSME_PTIO", SPT_PMC_BIT_CSME_PTIO}, + {"CSME_USBR", SPT_PMC_BIT_CSME_USBR}, + {"CSME_SUSRAM", SPT_PMC_BIT_CSME_SUSRAM}, + {"CSME_SMT", SPT_PMC_BIT_CSME_SMT}, + {"RSVD", SPT_PMC_BIT_RSVD_1A}, + {"CSME_SMS2", SPT_PMC_BIT_CSME_SMS2}, + {"CSME_SMS1", SPT_PMC_BIT_CSME_SMS1}, + {"CSME_RTC", SPT_PMC_BIT_CSME_RTC}, + {"CSME_PSF", SPT_PMC_BIT_CSME_PSF}, + {} +}; + +const struct pmc_bit_map *ext_spt_pfear_map[] = { + /* + * Check intel_pmc_core_ids[] users of spt_reg_map for + * a list of core SoCs using this. + */ + spt_pfear_map, + NULL +}; + +const struct pmc_bit_map spt_ltr_show_map[] = { + {"SOUTHPORT_A", SPT_PMC_LTR_SPA}, + {"SOUTHPORT_B", SPT_PMC_LTR_SPB}, + {"SATA", SPT_PMC_LTR_SATA}, + {"GIGABIT_ETHERNET", SPT_PMC_LTR_GBE}, + {"XHCI", SPT_PMC_LTR_XHCI}, + {"Reserved", SPT_PMC_LTR_RESERVED}, + {"ME", SPT_PMC_LTR_ME}, + /* EVA is Enterprise Value Add, doesn't really exist on PCH */ + {"EVA", SPT_PMC_LTR_EVA}, + {"SOUTHPORT_C", SPT_PMC_LTR_SPC}, + {"HD_AUDIO", SPT_PMC_LTR_AZ}, + {"LPSS", SPT_PMC_LTR_LPSS}, + {"SOUTHPORT_D", SPT_PMC_LTR_SPD}, + {"SOUTHPORT_E", SPT_PMC_LTR_SPE}, + {"CAMERA", SPT_PMC_LTR_CAM}, + {"ESPI", SPT_PMC_LTR_ESPI}, + {"SCC", SPT_PMC_LTR_SCC}, + {"ISH", SPT_PMC_LTR_ISH}, + /* Below two cannot be used for LTR_IGNORE */ + {"CURRENT_PLATFORM", SPT_PMC_LTR_CUR_PLT}, + {"AGGREGATED_SYSTEM", SPT_PMC_LTR_CUR_ASLT}, + {} +}; + +const struct pmc_reg_map spt_reg_map = { + .pfear_sts = ext_spt_pfear_map, + .mphy_sts = spt_mphy_map, + .pll_sts = spt_pll_map, + .ltr_show_sts = spt_ltr_show_map, + .msr_sts = msr_map, + .slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET, + .slp_s0_res_counter_step = SPT_PMC_SLP_S0_RES_COUNTER_STEP, + .ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET, + .regmap_length = SPT_PMC_MMIO_REG_LEN, + .ppfear0_offset = SPT_PMC_XRAM_PPFEAR0A, + .ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES, + .pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET, + .pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT, + .ltr_ignore_max = SPT_NUM_IP_IGN_ALLOWED, + .pm_vric1_offset = SPT_PMC_VRIC1_OFFSET, +}; + +void spt_core_init(struct pmc_dev *pmcdev) +{ + pmcdev->map = &spt_reg_map; +} diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c new file mode 100644 index 000000000000..e3e50538465d --- /dev/null +++ b/drivers/platform/x86/intel/pmc/tgl.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file contains platform specific structure definitions + * and init function used by Tiger Lake PCH. + * + * Copyright (c) 2022, Intel Corporation. + * All Rights Reserved. + * + */ + +#include "core.h" + +#define ACPI_S0IX_DSM_UUID "57a6512e-3979-4e9d-9708-ff13b2508972" +#define ACPI_GET_LOW_MODE_REGISTERS 1 + +const struct pmc_bit_map tgl_pfear_map[] = { + {"PSF9", BIT(0)}, + {"RES_66", BIT(1)}, + {"RES_67", BIT(2)}, + {"RES_68", BIT(3)}, + {"RES_69", BIT(4)}, + {"RES_70", BIT(5)}, + {"TBTLSX", BIT(6)}, + {} +}; + +const struct pmc_bit_map *ext_tgl_pfear_map[] = { + /* + * Check intel_pmc_core_ids[] users of tgl_reg_map for + * a list of core SoCs using this. + */ + cnp_pfear_map, + tgl_pfear_map, + NULL +}; + +const struct pmc_bit_map tgl_clocksource_status_map[] = { + {"USB2PLL_OFF_STS", BIT(18)}, + {"PCIe/USB3.1_Gen2PLL_OFF_STS", BIT(19)}, + {"PCIe_Gen3PLL_OFF_STS", BIT(20)}, + {"OPIOPLL_OFF_STS", BIT(21)}, + {"OCPLL_OFF_STS", BIT(22)}, + {"MainPLL_OFF_STS", BIT(23)}, + {"MIPIPLL_OFF_STS", BIT(24)}, + {"Fast_XTAL_Osc_OFF_STS", BIT(25)}, + {"AC_Ring_Osc_OFF_STS", BIT(26)}, + {"MC_Ring_Osc_OFF_STS", BIT(27)}, + {"SATAPLL_OFF_STS", BIT(29)}, + {"XTAL_USB2PLL_OFF_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map tgl_power_gating_status_map[] = { + {"CSME_PG_STS", BIT(0)}, + {"SATA_PG_STS", BIT(1)}, + {"xHCI_PG_STS", BIT(2)}, + {"UFSX2_PG_STS", BIT(3)}, + {"OTG_PG_STS", BIT(5)}, + {"SPA_PG_STS", BIT(6)}, + {"SPB_PG_STS", BIT(7)}, + {"SPC_PG_STS", BIT(8)}, + {"SPD_PG_STS", BIT(9)}, + {"SPE_PG_STS", BIT(10)}, + {"SPF_PG_STS", BIT(11)}, + {"LSX_PG_STS", BIT(13)}, + {"P2SB_PG_STS", BIT(14)}, + {"PSF_PG_STS", BIT(15)}, + {"SBR_PG_STS", BIT(16)}, + {"OPIDMI_PG_STS", BIT(17)}, + {"THC0_PG_STS", BIT(18)}, + {"THC1_PG_STS", BIT(19)}, + {"GBETSN_PG_STS", BIT(20)}, + {"GBE_PG_STS", BIT(21)}, + {"LPSS_PG_STS", BIT(22)}, + {"MMP_UFSX2_PG_STS", BIT(23)}, + {"MMP_UFSX2B_PG_STS", BIT(24)}, + {"FIA_PG_STS", BIT(25)}, + {} +}; + +const struct pmc_bit_map tgl_d3_status_map[] = { + {"ADSP_D3_STS", BIT(0)}, + {"SATA_D3_STS", BIT(1)}, + {"xHCI0_D3_STS", BIT(2)}, + {"xDCI1_D3_STS", BIT(5)}, + {"SDX_D3_STS", BIT(6)}, + {"EMMC_D3_STS", BIT(7)}, + {"IS_D3_STS", BIT(8)}, + {"THC0_D3_STS", BIT(9)}, + {"THC1_D3_STS", BIT(10)}, + {"GBE_D3_STS", BIT(11)}, + {"GBE_TSN_D3_STS", BIT(12)}, + {} +}; + +const struct pmc_bit_map tgl_vnn_req_status_map[] = { + {"GPIO_COM0_VNN_REQ_STS", BIT(1)}, + {"GPIO_COM1_VNN_REQ_STS", BIT(2)}, + {"GPIO_COM2_VNN_REQ_STS", BIT(3)}, + {"GPIO_COM3_VNN_REQ_STS", BIT(4)}, + {"GPIO_COM4_VNN_REQ_STS", BIT(5)}, + {"GPIO_COM5_VNN_REQ_STS", BIT(6)}, + {"Audio_VNN_REQ_STS", BIT(7)}, + {"ISH_VNN_REQ_STS", BIT(8)}, + {"CNVI_VNN_REQ_STS", BIT(9)}, + {"eSPI_VNN_REQ_STS", BIT(10)}, + {"Display_VNN_REQ_STS", BIT(11)}, + {"DTS_VNN_REQ_STS", BIT(12)}, + {"SMBUS_VNN_REQ_STS", BIT(14)}, + {"CSME_VNN_REQ_STS", BIT(15)}, + {"SMLINK0_VNN_REQ_STS", BIT(16)}, + {"SMLINK1_VNN_REQ_STS", BIT(17)}, + {"CLINK_VNN_REQ_STS", BIT(20)}, + {"DCI_VNN_REQ_STS", BIT(21)}, + {"ITH_VNN_REQ_STS", BIT(22)}, + {"CSME_VNN_REQ_STS", BIT(24)}, + {"GBE_VNN_REQ_STS", BIT(25)}, + {} +}; + +const struct pmc_bit_map tgl_vnn_misc_status_map[] = { + {"CPU_C10_REQ_STS_0", BIT(0)}, + {"PCIe_LPM_En_REQ_STS_3", BIT(3)}, + {"ITH_REQ_STS_5", BIT(5)}, + {"CNVI_REQ_STS_6", BIT(6)}, + {"ISH_REQ_STS_7", BIT(7)}, + {"USB2_SUS_PG_Sys_REQ_STS_10", BIT(10)}, + {"PCIe_Clk_REQ_STS_12", BIT(12)}, + {"MPHY_Core_DL_REQ_STS_16", BIT(16)}, + {"Break-even_En_REQ_STS_17", BIT(17)}, + {"Auto-demo_En_REQ_STS_18", BIT(18)}, + {"MPHY_SUS_REQ_STS_22", BIT(22)}, + {"xDCI_attached_REQ_STS_24", BIT(24)}, + {} +}; + +const struct pmc_bit_map tgl_signal_status_map[] = { + {"LSX_Wake0_En_STS", BIT(0)}, + {"LSX_Wake0_Pol_STS", BIT(1)}, + {"LSX_Wake1_En_STS", BIT(2)}, + {"LSX_Wake1_Pol_STS", BIT(3)}, + {"LSX_Wake2_En_STS", BIT(4)}, + {"LSX_Wake2_Pol_STS", BIT(5)}, + {"LSX_Wake3_En_STS", BIT(6)}, + {"LSX_Wake3_Pol_STS", BIT(7)}, + {"LSX_Wake4_En_STS", BIT(8)}, + {"LSX_Wake4_Pol_STS", BIT(9)}, + {"LSX_Wake5_En_STS", BIT(10)}, + {"LSX_Wake5_Pol_STS", BIT(11)}, + {"LSX_Wake6_En_STS", BIT(12)}, + {"LSX_Wake6_Pol_STS", BIT(13)}, + {"LSX_Wake7_En_STS", BIT(14)}, + {"LSX_Wake7_Pol_STS", BIT(15)}, + {"Intel_Se_IO_Wake0_En_STS", BIT(16)}, + {"Intel_Se_IO_Wake0_Pol_STS", BIT(17)}, + {"Intel_Se_IO_Wake1_En_STS", BIT(18)}, + {"Intel_Se_IO_Wake1_Pol_STS", BIT(19)}, + {"Int_Timer_SS_Wake0_En_STS", BIT(20)}, + {"Int_Timer_SS_Wake0_Pol_STS", BIT(21)}, + {"Int_Timer_SS_Wake1_En_STS", BIT(22)}, + {"Int_Timer_SS_Wake1_Pol_STS", BIT(23)}, + {"Int_Timer_SS_Wake2_En_STS", BIT(24)}, + {"Int_Timer_SS_Wake2_Pol_STS", BIT(25)}, + {"Int_Timer_SS_Wake3_En_STS", BIT(26)}, + {"Int_Timer_SS_Wake3_Pol_STS", BIT(27)}, + {"Int_Timer_SS_Wake4_En_STS", BIT(28)}, + {"Int_Timer_SS_Wake4_Pol_STS", BIT(29)}, + {"Int_Timer_SS_Wake5_En_STS", BIT(30)}, + {"Int_Timer_SS_Wake5_Pol_STS", BIT(31)}, + {} +}; + +const struct pmc_bit_map *tgl_lpm_maps[] = { + tgl_clocksource_status_map, + tgl_power_gating_status_map, + tgl_d3_status_map, + tgl_vnn_req_status_map, + tgl_vnn_misc_status_map, + tgl_signal_status_map, + NULL +}; + +const struct pmc_reg_map tgl_reg_map = { + .pfear_sts = ext_tgl_pfear_map, + .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, + .slp_s0_res_counter_step = TGL_PMC_SLP_S0_RES_COUNTER_STEP, + .ltr_show_sts = cnp_ltr_show_map, + .msr_sts = msr_map, + .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, + .regmap_length = CNP_PMC_MMIO_REG_LEN, + .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, + .ppfear_buckets = ICL_PPFEAR_NUM_ENTRIES, + .pm_cfg_offset = CNP_PMC_PM_CFG_OFFSET, + .pm_read_disable_bit = CNP_PMC_READ_DISABLE_BIT, + .ltr_ignore_max = TGL_NUM_IP_IGN_ALLOWED, + .lpm_num_maps = TGL_LPM_NUM_MAPS, + .lpm_res_counter_step_x2 = TGL_PMC_LPM_RES_COUNTER_STEP_X2, + .lpm_sts_latch_en_offset = TGL_LPM_STS_LATCH_EN_OFFSET, + .lpm_en_offset = TGL_LPM_EN_OFFSET, + .lpm_priority_offset = TGL_LPM_PRI_OFFSET, + .lpm_residency_offset = TGL_LPM_RESIDENCY_OFFSET, + .lpm_sts = tgl_lpm_maps, + .lpm_status_offset = TGL_LPM_STATUS_OFFSET, + .lpm_live_status_offset = TGL_LPM_LIVE_STATUS_OFFSET, + .etr3_offset = ETR3_OFFSET, +}; + +void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev) +{ + struct pmc_dev *pmcdev = platform_get_drvdata(pdev); + const int num_maps = pmcdev->map->lpm_num_maps; + u32 lpm_size = LPM_MAX_NUM_MODES * num_maps * 4; + union acpi_object *out_obj; + struct acpi_device *adev; + guid_t s0ix_dsm_guid; + u32 *lpm_req_regs, *addr; + + adev = ACPI_COMPANION(&pdev->dev); + if (!adev) + return; + + guid_parse(ACPI_S0IX_DSM_UUID, &s0ix_dsm_guid); + + out_obj = acpi_evaluate_dsm(adev->handle, &s0ix_dsm_guid, 0, + ACPI_GET_LOW_MODE_REGISTERS, NULL); + if (out_obj && out_obj->type == ACPI_TYPE_BUFFER) { + u32 size = out_obj->buffer.length; + + if (size != lpm_size) { + acpi_handle_debug(adev->handle, + "_DSM returned unexpected buffer size, have %u, expect %u\n", + size, lpm_size); + goto free_acpi_obj; + } + } else { + acpi_handle_debug(adev->handle, + "_DSM function 0 evaluation failed\n"); + goto free_acpi_obj; + } + + addr = (u32 *)out_obj->buffer.pointer; + + lpm_req_regs = devm_kzalloc(&pdev->dev, lpm_size * sizeof(u32), + GFP_KERNEL); + if (!lpm_req_regs) + goto free_acpi_obj; + + memcpy(lpm_req_regs, addr, lpm_size); + pmcdev->lpm_req_regs = lpm_req_regs; + +free_acpi_obj: + ACPI_FREE(out_obj); +} + +void tgl_core_configure(struct pmc_dev *pmcdev) +{ + pmc_core_get_tgl_lpm_reqs(pmcdev->pdev); + /* Due to a hardware limitation, the GBE LTR blocks PC10 + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); + pmc_core_send_ltr_ignore(pmcdev, 3); +} + +void tgl_core_init(struct pmc_dev *pmcdev) +{ + pmcdev->map = &tgl_reg_map; + pmcdev->core_configure = tgl_core_configure; +} diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c index c830e98dfa38..9e0ea2cdd704 100644 --- a/drivers/platform/x86/intel/sdsi.c +++ b/drivers/platform/x86/intel/sdsi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Intel Software Defined Silicon driver + * Intel On Demand (Software Defined Silicon) driver * * Copyright (c) 2022, Intel Corporation. * All Rights Reserved. @@ -27,9 +27,8 @@ #define ACCESS_TYPE_LOCAL 3 #define SDSI_MIN_SIZE_DWORDS 276 -#define SDSI_SIZE_CONTROL 8 #define SDSI_SIZE_MAILBOX 1024 -#define SDSI_SIZE_REGS 72 +#define SDSI_SIZE_REGS 80 #define SDSI_SIZE_CMD sizeof(u64) /* @@ -41,7 +40,9 @@ #define SDSI_SIZE_READ_MSG (SDSI_SIZE_MAILBOX * 4) #define SDSI_ENABLED_FEATURES_OFFSET 16 -#define SDSI_ENABLED BIT(3) +#define SDSI_FEATURE_SDSI BIT(3) +#define SDSI_FEATURE_METERING BIT(26) + #define SDSI_SOCKET_ID_OFFSET 64 #define SDSI_SOCKET_ID GENMASK(3, 0) @@ -75,10 +76,18 @@ #define DT_TBIR GENMASK(2, 0) #define DT_OFFSET(v) ((v) & GENMASK(31, 3)) +#define SDSI_GUID_V1 0x006DD191 +#define GUID_V1_CNTRL_SIZE 8 +#define GUID_V1_REGS_SIZE 72 +#define SDSI_GUID_V2 0xF210D9EF +#define GUID_V2_CNTRL_SIZE 16 +#define GUID_V2_REGS_SIZE 80 + enum sdsi_command { - SDSI_CMD_PROVISION_AKC = 0x04, - SDSI_CMD_PROVISION_CAP = 0x08, - SDSI_CMD_READ_STATE = 0x10, + SDSI_CMD_PROVISION_AKC = 0x0004, + SDSI_CMD_PROVISION_CAP = 0x0008, + SDSI_CMD_READ_STATE = 0x0010, + SDSI_CMD_READ_METER = 0x0014, }; struct sdsi_mbox_info { @@ -99,8 +108,11 @@ struct sdsi_priv { void __iomem *control_addr; void __iomem *mbox_addr; void __iomem *regs_addr; + int control_size; + int maibox_size; + int registers_size; u32 guid; - bool sdsi_enabled; + u32 features; }; /* SDSi mailbox operations must be performed using 64bit mov instructions */ @@ -332,9 +344,6 @@ static ssize_t sdsi_provision(struct sdsi_priv *priv, char *buf, size_t count, struct sdsi_mbox_info info; int ret; - if (!priv->sdsi_enabled) - return -EPERM; - if (count > (SDSI_SIZE_WRITE_MSG - SDSI_SIZE_CMD)) return -EOVERFLOW; @@ -394,20 +403,14 @@ static ssize_t provision_cap_write(struct file *filp, struct kobject *kobj, } static BIN_ATTR_WO(provision_cap, SDSI_SIZE_WRITE_MSG); -static long state_certificate_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, loff_t off, - size_t count) +static ssize_t +certificate_read(u64 command, struct sdsi_priv *priv, char *buf, loff_t off, + size_t count) { - struct device *dev = kobj_to_dev(kobj); - struct sdsi_priv *priv = dev_get_drvdata(dev); - u64 command = SDSI_CMD_READ_STATE; struct sdsi_mbox_info info; size_t size; int ret; - if (!priv->sdsi_enabled) - return -EPERM; - if (off) return 0; @@ -440,7 +443,30 @@ free_buffer: return size; } -static BIN_ATTR(state_certificate, 0400, state_certificate_read, NULL, SDSI_SIZE_READ_MSG); + +static ssize_t +state_certificate_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, + size_t count) +{ + struct device *dev = kobj_to_dev(kobj); + struct sdsi_priv *priv = dev_get_drvdata(dev); + + return certificate_read(SDSI_CMD_READ_STATE, priv, buf, off, count); +} +static BIN_ATTR_ADMIN_RO(state_certificate, SDSI_SIZE_READ_MSG); + +static ssize_t +meter_certificate_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, + size_t count) +{ + struct device *dev = kobj_to_dev(kobj); + struct sdsi_priv *priv = dev_get_drvdata(dev); + + return certificate_read(SDSI_CMD_READ_METER, priv, buf, off, count); +} +static BIN_ATTR_ADMIN_RO(meter_certificate, SDSI_SIZE_READ_MSG); static ssize_t registers_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, @@ -449,21 +475,55 @@ static ssize_t registers_read(struct file *filp, struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct sdsi_priv *priv = dev_get_drvdata(dev); void __iomem *addr = priv->regs_addr; + int size = priv->registers_size; + + /* + * The check below is performed by the sysfs caller based on the static + * file size. But this may be greater than the actual size which is based + * on the GUID. So check here again based on actual size before reading. + */ + if (off >= size) + return 0; + + if (off + count > size) + count = size - off; memcpy_fromio(buf, addr + off, count); return count; } -static BIN_ATTR(registers, 0400, registers_read, NULL, SDSI_SIZE_REGS); +static BIN_ATTR_ADMIN_RO(registers, SDSI_SIZE_REGS); static struct bin_attribute *sdsi_bin_attrs[] = { &bin_attr_registers, &bin_attr_state_certificate, + &bin_attr_meter_certificate, &bin_attr_provision_akc, &bin_attr_provision_cap, NULL }; +static umode_t +sdsi_battr_is_visible(struct kobject *kobj, struct bin_attribute *attr, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct sdsi_priv *priv = dev_get_drvdata(dev); + + /* Registers file is always readable if the device is present */ + if (attr == &bin_attr_registers) + return attr->attr.mode; + + /* All other attributes not visible if BIOS has not enabled On Demand */ + if (!(priv->features & SDSI_FEATURE_SDSI)) + return 0; + + if (attr == &bin_attr_meter_certificate) + return (priv->features & SDSI_FEATURE_METERING) ? + attr->attr.mode : 0; + + return attr->attr.mode; +} + static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct sdsi_priv *priv = dev_get_drvdata(dev); @@ -480,9 +540,28 @@ static struct attribute *sdsi_attrs[] = { static const struct attribute_group sdsi_group = { .attrs = sdsi_attrs, .bin_attrs = sdsi_bin_attrs, + .is_bin_visible = sdsi_battr_is_visible, }; __ATTRIBUTE_GROUPS(sdsi); +static int sdsi_get_layout(struct sdsi_priv *priv, struct disc_table *table) +{ + switch (table->guid) { + case SDSI_GUID_V1: + priv->control_size = GUID_V1_CNTRL_SIZE; + priv->registers_size = GUID_V1_REGS_SIZE; + break; + case SDSI_GUID_V2: + priv->control_size = GUID_V2_CNTRL_SIZE; + priv->registers_size = GUID_V2_REGS_SIZE; + break; + default: + dev_err(priv->dev, "Unrecognized GUID 0x%x\n", table->guid); + return -EINVAL; + } + return 0; +} + static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *parent, struct disc_table *disc_table, struct resource *disc_res) { @@ -490,7 +569,6 @@ static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *paren u32 size = FIELD_GET(DT_SIZE, disc_table->access_info); u32 tbir = FIELD_GET(DT_TBIR, disc_table->offset); u32 offset = DT_OFFSET(disc_table->offset); - u32 features_offset; struct resource res = {}; /* Starting location of SDSi MMIO region based on access type */ @@ -525,11 +603,10 @@ static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *paren if (IS_ERR(priv->control_addr)) return PTR_ERR(priv->control_addr); - priv->mbox_addr = priv->control_addr + SDSI_SIZE_CONTROL; + priv->mbox_addr = priv->control_addr + priv->control_size; priv->regs_addr = priv->mbox_addr + SDSI_SIZE_MAILBOX; - features_offset = readq(priv->regs_addr + SDSI_ENABLED_FEATURES_OFFSET); - priv->sdsi_enabled = !!(features_offset & SDSI_ENABLED); + priv->features = readq(priv->regs_addr + SDSI_ENABLED_FEATURES_OFFSET); return 0; } @@ -561,6 +638,11 @@ static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_de priv->guid = disc_table.guid; + /* Get guid based layout info */ + ret = sdsi_get_layout(priv, &disc_table); + if (ret) + return ret; + /* Map the SDSi mailbox registers */ ret = sdsi_map_mbox_registers(priv, intel_cap_dev->pcidev, &disc_table, disc_res); if (ret) @@ -586,5 +668,5 @@ static struct auxiliary_driver sdsi_aux_driver = { module_auxiliary_driver(sdsi_aux_driver); MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>"); -MODULE_DESCRIPTION("Intel Software Defined Silicon driver"); +MODULE_DESCRIPTION("Intel On Demand (SDSi) driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c index fd102678c75f..a7e02b24a87a 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c @@ -623,7 +623,7 @@ static long isst_if_def_ioctl(struct file *file, unsigned int cmd, /* Lock to prevent module registration when already opened by user space */ static DEFINE_MUTEX(punit_misc_dev_open_lock); -/* Lock to allow one share misc device for all ISST interace */ +/* Lock to allow one shared misc device for all ISST interfaces */ static DEFINE_MUTEX(punit_misc_dev_reg_lock); static int misc_usage_count; static int misc_device_ret; diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c index 8f9c571d7257..00ac7e381441 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c @@ -203,6 +203,7 @@ static const struct x86_cpu_id intel_uncore_cpu_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, NULL), X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, NULL), X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, NULL), + X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, NULL), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_uncore_cpu_ids); |