1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * Intel PMC Core platform init 5 * Copyright (c) 2019, Google Inc. 6 * Author - Rajat Jain 7 * 8 * This code instantiates platform devices for intel_pmc_core driver, only 9 * on supported platforms that may not have the ACPI devices in the ACPI tables. 10 * No new platforms should be added here, because we expect that new platforms 11 * should all have the ACPI device, which is the preferred way of enumeration. 12 */ 13 14 #include <linux/acpi.h> 15 #include <linux/module.h> 16 #include <linux/platform_device.h> 17 18 #include <asm/cpu_device_id.h> 19 #include <asm/intel-family.h> 20 21 #include <xen/xen.h> 22 23 static void intel_pmc_core_release(struct device *dev) 24 { 25 kfree(dev); 26 } 27 28 static struct platform_device *pmc_core_device; 29 30 /* 31 * intel_pmc_core_platform_ids is the list of platforms where we want to 32 * instantiate the platform_device if not already instantiated. This is 33 * different than intel_pmc_core_ids in intel_pmc_core.c which is the 34 * list of platforms that the driver supports for pmc_core device. The 35 * other list may grow, but this list should not. 36 */ 37 static const struct x86_cpu_id intel_pmc_core_platform_ids[] = { 38 X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, &pmc_core_device), 39 X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, &pmc_core_device), 40 X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, &pmc_core_device), 41 X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, &pmc_core_device), 42 X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, &pmc_core_device), 43 X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, &pmc_core_device), 44 X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, &pmc_core_device), 45 X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, &pmc_core_device), 46 {} 47 }; 48 MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_platform_ids); 49 50 static int __init pmc_core_platform_init(void) 51 { 52 int retval; 53 54 /* Skip creating the platform device if ACPI already has a device */ 55 if (acpi_dev_present("INT33A1", NULL, -1)) 56 return -ENODEV; 57 58 /* 59 * Skip forcefully attaching the device for VMs. Make an exception for 60 * Xen dom0, which does have full hardware access. 61 */ 62 if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR) && !xen_initial_domain()) 63 return -ENODEV; 64 65 if (!x86_match_cpu(intel_pmc_core_platform_ids)) 66 return -ENODEV; 67 68 pmc_core_device = kzalloc(sizeof(*pmc_core_device), GFP_KERNEL); 69 if (!pmc_core_device) 70 return -ENOMEM; 71 72 pmc_core_device->name = "intel_pmc_core"; 73 pmc_core_device->dev.release = intel_pmc_core_release; 74 75 retval = platform_device_register(pmc_core_device); 76 if (retval) 77 platform_device_put(pmc_core_device); 78 79 return retval; 80 } 81 82 static void __exit pmc_core_platform_exit(void) 83 { 84 platform_device_unregister(pmc_core_device); 85 } 86 87 module_init(pmc_core_platform_init); 88 module_exit(pmc_core_platform_exit); 89 MODULE_LICENSE("GPL v2"); 90