diff options
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/mellanox/mlxreg-hotplug.c | 28 | ||||
-rw-r--r-- | drivers/platform/x86/asus-wmi.c | 9 | ||||
-rw-r--r-- | drivers/platform/x86/dell-smbios-wmi.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/dell-wmi-descriptor.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/dell-wmi.c | 7 | ||||
-rw-r--r-- | drivers/platform/x86/dell_rbu.c | 50 | ||||
-rw-r--r-- | drivers/platform/x86/huawei-wmi.c | 3 | ||||
-rw-r--r-- | drivers/platform/x86/i2c-multi-instantiate.c | 9 | ||||
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 37 | ||||
-rw-r--r-- | drivers/platform/x86/intel-hid.c | 7 | ||||
-rw-r--r-- | drivers/platform/x86/intel-wmi-thunderbolt.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/intel_int0002_vgpio.c | 32 | ||||
-rw-r--r-- | drivers/platform/x86/intel_pmc_core.c | 159 | ||||
-rw-r--r-- | drivers/platform/x86/intel_pmc_core.h | 14 | ||||
-rw-r--r-- | drivers/platform/x86/mlx-platform.c | 105 | ||||
-rw-r--r-- | drivers/platform/x86/touchscreen_dmi.c | 79 | ||||
-rw-r--r-- | drivers/platform/x86/wmi-bmof.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/wmi.c | 5 |
18 files changed, 460 insertions, 92 deletions
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index b6d44550d98c..687ce6817d0d 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -248,7 +248,8 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv, struct mlxreg_core_item *item) { struct mlxreg_core_data *data; - u32 asserted, regval, bit; + unsigned long asserted; + u32 regval, bit; int ret; /* @@ -281,7 +282,7 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv, asserted = item->cache ^ regval; item->cache = regval; - for_each_set_bit(bit, (unsigned long *)&asserted, 8) { + for_each_set_bit(bit, &asserted, 8) { data = item->data + bit; if (regval & BIT(bit)) { if (item->inversed) @@ -495,7 +496,9 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) { struct mlxreg_core_hotplug_platform_data *pdata; struct mlxreg_core_item *item; - int i, ret; + struct mlxreg_core_data *data; + u32 regval; + int i, j, ret; pdata = dev_get_platdata(&priv->pdev->dev); item = pdata->items; @@ -507,6 +510,25 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) if (ret) goto out; + /* + * Verify if hardware configuration requires to disable + * interrupt capability for some of components. + */ + data = item->data; + for (j = 0; j < item->count; j++, data++) { + /* Verify if the attribute has capability register. */ + if (data->capability) { + /* Read capability register. */ + ret = regmap_read(priv->regmap, + data->capability, ®val); + if (ret) + goto out; + + if (!(regval & data->bit)) + item->mask &= ~BIT(j); + } + } + /* Set group initial status as mask and unmask group event. */ if (item->inversed) { item->cache = item->mask; diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 37b5de541270..ee1fa93708ec 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -2265,12 +2265,12 @@ static int asus_wmi_probe(struct platform_device *pdev) int ret; if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) { - pr_warn("Management GUID not found\n"); + pr_warn("ASUS Management GUID not found\n"); return -ENODEV; } if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) { - pr_warn("Event GUID not found\n"); + pr_warn("ASUS Event GUID not found\n"); return -ENODEV; } @@ -2320,11 +2320,6 @@ EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver); static int __init asus_wmi_init(void) { - if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) { - pr_info("Asus Management GUID not found\n"); - return -ENODEV; - } - pr_info("ASUS WMI generic driver loaded\n"); return 0; } diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c index cf2229ece9ff..c3ed3c8c17b9 100644 --- a/drivers/platform/x86/dell-smbios-wmi.c +++ b/drivers/platform/x86/dell-smbios-wmi.c @@ -277,4 +277,4 @@ void exit_dell_smbios_wmi(void) wmi_driver_unregister(&dell_smbios_wmi_driver); } -MODULE_ALIAS("wmi:" DELL_WMI_SMBIOS_GUID); +MODULE_DEVICE_TABLE(wmi, dell_smbios_wmi_id_table); diff --git a/drivers/platform/x86/dell-wmi-descriptor.c b/drivers/platform/x86/dell-wmi-descriptor.c index 072821aa47fc..14ab250b7d5a 100644 --- a/drivers/platform/x86/dell-wmi-descriptor.c +++ b/drivers/platform/x86/dell-wmi-descriptor.c @@ -207,7 +207,7 @@ static struct wmi_driver dell_wmi_descriptor_driver = { module_wmi_driver(dell_wmi_descriptor_driver); -MODULE_ALIAS("wmi:" DELL_WMI_DESCRIPTOR_GUID); +MODULE_DEVICE_TABLE(wmi, dell_wmi_descriptor_id_table); MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>"); MODULE_DESCRIPTION("Dell WMI descriptor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 16c7f3d9a335..d118bb73fcae 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -50,8 +50,6 @@ MODULE_LICENSE("GPL"); static bool wmi_requires_smbios_request; -MODULE_ALIAS("wmi:"DELL_EVENT_GUID); - struct dell_wmi_priv { struct input_dev *input_dev; u32 interface_version; @@ -267,6 +265,9 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = { /* Fn-lock switched to multimedia keys */ { KE_IGNORE, 0x1, { KEY_RESERVED } }, + /* Keyboard backlight change notification */ + { KE_IGNORE, 0x3f, { KEY_RESERVED } }, + /* Mic mute */ { KE_KEY, 0x150, { KEY_MICMUTE } }, @@ -738,3 +739,5 @@ static void __exit dell_wmi_exit(void) wmi_driver_unregister(&dell_wmi_driver); } module_exit(dell_wmi_exit); + +MODULE_DEVICE_TABLE(wmi, dell_wmi_id_table); diff --git a/drivers/platform/x86/dell_rbu.c b/drivers/platform/x86/dell_rbu.c index ccefa84f7305..031c68903583 100644 --- a/drivers/platform/x86/dell_rbu.c +++ b/drivers/platform/x86/dell_rbu.c @@ -59,7 +59,6 @@ static struct _rbu_data { unsigned long image_update_buffer_size; unsigned long bios_image_size; int image_update_ordernum; - int dma_alloc; spinlock_t lock; unsigned long packet_read_count; unsigned long num_packets; @@ -89,7 +88,6 @@ static struct packet_data packet_data_head; static struct platform_device *rbu_device; static int context; -static dma_addr_t dell_rbu_dmaaddr; static void init_packet_head(void) { @@ -380,12 +378,8 @@ static void img_update_free(void) */ memset(rbu_data.image_update_buffer, 0, rbu_data.image_update_buffer_size); - if (rbu_data.dma_alloc == 1) - dma_free_coherent(NULL, rbu_data.bios_image_size, - rbu_data.image_update_buffer, dell_rbu_dmaaddr); - else - free_pages((unsigned long) rbu_data.image_update_buffer, - rbu_data.image_update_ordernum); + free_pages((unsigned long) rbu_data.image_update_buffer, + rbu_data.image_update_ordernum); /* * Re-initialize the rbu_data variables after a free @@ -394,7 +388,6 @@ static void img_update_free(void) rbu_data.image_update_buffer = NULL; rbu_data.image_update_buffer_size = 0; rbu_data.bios_image_size = 0; - rbu_data.dma_alloc = 0; } /* @@ -410,10 +403,8 @@ static void img_update_free(void) static int img_update_realloc(unsigned long size) { unsigned char *image_update_buffer = NULL; - unsigned long rc; unsigned long img_buf_phys_addr; int ordernum; - int dma_alloc = 0; /* * check if the buffer of sufficient size has been @@ -444,36 +435,23 @@ static int img_update_realloc(unsigned long size) ordernum = get_order(size); image_update_buffer = - (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); - - img_buf_phys_addr = - (unsigned long) virt_to_phys(image_update_buffer); - - if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { - free_pages((unsigned long) image_update_buffer, ordernum); - ordernum = -1; - image_update_buffer = dma_alloc_coherent(NULL, size, - &dell_rbu_dmaaddr, GFP_KERNEL); - dma_alloc = 1; - } - + (unsigned char *)__get_free_pages(GFP_DMA32, ordernum); spin_lock(&rbu_data.lock); - - if (image_update_buffer != NULL) { - rbu_data.image_update_buffer = image_update_buffer; - rbu_data.image_update_buffer_size = size; - rbu_data.bios_image_size = - rbu_data.image_update_buffer_size; - rbu_data.image_update_ordernum = ordernum; - rbu_data.dma_alloc = dma_alloc; - rc = 0; - } else { + if (!image_update_buffer) { pr_debug("Not enough memory for image update:" "size = %ld\n", size); - rc = -ENOMEM; + return -ENOMEM; } - return rc; + img_buf_phys_addr = (unsigned long)virt_to_phys(image_update_buffer); + if (WARN_ON_ONCE(img_buf_phys_addr > BIOS_SCAN_LIMIT)) + return -EINVAL; /* can't happen per definition */ + + rbu_data.image_update_buffer = image_update_buffer; + rbu_data.image_update_buffer_size = size; + rbu_data.bios_image_size = rbu_data.image_update_buffer_size; + rbu_data.image_update_ordernum = ordernum; + return 0; } static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c index 59872f87b741..52fcac5b393a 100644 --- a/drivers/platform/x86/huawei-wmi.c +++ b/drivers/platform/x86/huawei-wmi.c @@ -201,8 +201,7 @@ static struct wmi_driver huawei_wmi_driver = { module_wmi_driver(huawei_wmi_driver); -MODULE_ALIAS("wmi:"WMI0_EVENT_GUID); -MODULE_ALIAS("wmi:"AMW0_EVENT_GUID); +MODULE_DEVICE_TABLE(wmi, huawei_wmi_id_table); MODULE_AUTHOR("Ayman Bagabas <ayman.bagabas@gmail.com>"); MODULE_DESCRIPTION("Huawei WMI hotkeys"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/i2c-multi-instantiate.c b/drivers/platform/x86/i2c-multi-instantiate.c index 3d893e0ac250..197d8a192721 100644 --- a/drivers/platform/x86/i2c-multi-instantiate.c +++ b/drivers/platform/x86/i2c-multi-instantiate.c @@ -159,6 +159,14 @@ static const struct i2c_inst_data bsg1160_data[] = { {} }; +static const struct i2c_inst_data bsg2150_data[] = { + { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 }, + { "bmc150_magn" }, + /* The resources describe a 3th client, but it is not really there. */ + { "bsg2150_dummy_dev" }, + {} +}; + static const struct i2c_inst_data int3515_data[] = { { "tps6598x", IRQ_RESOURCE_APIC, 0 }, { "tps6598x", IRQ_RESOURCE_APIC, 1 }, @@ -173,6 +181,7 @@ static const struct i2c_inst_data int3515_data[] = { */ static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = { { "BSG1160", (unsigned long)bsg1160_data }, + { "BSG2150", (unsigned long)bsg2150_data }, { "INT3515", (unsigned long)int3515_data }, { } }; diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 1589dffab9fa..c53ae86b59c7 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -989,7 +989,7 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { .ident = "Lenovo RESCUER R720-15IKBN", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_BOARD_NAME, "80WW"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo R720-15IKBN"), }, }, { @@ -1091,6 +1091,27 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { }, }, { + .ident = "Lenovo ideapad 330-15ICH", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 330-15ICH"), + }, + }, + { + .ident = "Lenovo ideapad 530S-14ARR", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 530S-14ARR"), + }, + }, + { + .ident = "Lenovo ideapad S130-14IGM", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad S130-14IGM"), + }, + }, + { .ident = "Lenovo ideapad Y700-14ISK", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -1154,6 +1175,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { }, }, { + .ident = "Lenovo Legion Y530-15ICH-1060", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion Y530-15ICH-1060"), + }, + }, + { .ident = "Lenovo Legion Y720-15IKB", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -1245,6 +1273,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = { }, }, { + .ident = "Lenovo YOGA C930-13IKB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA C930-13IKB"), + }, + }, + { .ident = "Lenovo Zhaoyang E42-80", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index e28bcf61b126..bc0d55a59015 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -363,7 +363,7 @@ wakeup: * the 5-button array, but still send notifies with power button * event code to this device object on power button actions. * - * Report the power button press; catch and ignore the button release. + * Report the power button press and release. */ if (!priv->array) { if (event == 0xce) { @@ -372,8 +372,11 @@ wakeup: return; } - if (event == 0xcf) + if (event == 0xcf) { + input_report_key(priv->input_dev, KEY_POWER, 0); + input_sync(priv->input_dev); return; + } } /* 0xC0 is for HID events, other values are for 5 button array */ diff --git a/drivers/platform/x86/intel-wmi-thunderbolt.c b/drivers/platform/x86/intel-wmi-thunderbolt.c index 9ded8e2af312..4dfa61434a76 100644 --- a/drivers/platform/x86/intel-wmi-thunderbolt.c +++ b/drivers/platform/x86/intel-wmi-thunderbolt.c @@ -88,7 +88,7 @@ static struct wmi_driver intel_wmi_thunderbolt_driver = { module_wmi_driver(intel_wmi_thunderbolt_driver); -MODULE_ALIAS("wmi:" INTEL_WMI_THUNDERBOLT_GUID); +MODULE_DEVICE_TABLE(wmi, intel_wmi_thunderbolt_id_table); MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>"); MODULE_DESCRIPTION("Intel WMI Thunderbolt force power driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c index 4b8f7305fc8a..1694a9aec77c 100644 --- a/drivers/platform/x86/intel_int0002_vgpio.c +++ b/drivers/platform/x86/intel_int0002_vgpio.c @@ -51,11 +51,14 @@ #define GPE0A_STS_PORT 0x420 #define GPE0A_EN_PORT 0x428 -#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } +#define BAYTRAIL 0x01 +#define CHERRYTRAIL 0x02 + +#define ICPU(model, data) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, data } static const struct x86_cpu_id int0002_cpu_ids[] = { - ICPU(INTEL_FAM6_ATOM_SILVERMONT), /* Valleyview, Bay Trail */ - ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */ + ICPU(INTEL_FAM6_ATOM_SILVERMONT, BAYTRAIL), /* Valleyview, Bay Trail */ + ICPU(INTEL_FAM6_ATOM_AIRMONT, CHERRYTRAIL), /* Braswell, Cherry Trail */ {} }; @@ -135,7 +138,7 @@ static irqreturn_t int0002_irq(int irq, void *data) return IRQ_HANDLED; } -static struct irq_chip int0002_irqchip = { +static struct irq_chip int0002_byt_irqchip = { .name = DRV_NAME, .irq_ack = int0002_irq_ack, .irq_mask = int0002_irq_mask, @@ -143,10 +146,22 @@ static struct irq_chip int0002_irqchip = { .irq_set_wake = int0002_irq_set_wake, }; +static struct irq_chip int0002_cht_irqchip = { + .name = DRV_NAME, + .irq_ack = int0002_irq_ack, + .irq_mask = int0002_irq_mask, + .irq_unmask = int0002_irq_unmask, + /* + * No set_wake, on CHT the IRQ is typically shared with the ACPI SCI + * and we don't want to mess with the ACPI SCI irq settings. + */ +}; + static int int0002_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct x86_cpu_id *cpu_id; + struct irq_chip *irq_chip; struct gpio_chip *chip; int irq, ret; @@ -195,14 +210,19 @@ static int int0002_probe(struct platform_device *pdev) return ret; } - ret = gpiochip_irqchip_add(chip, &int0002_irqchip, 0, handle_edge_irq, + if (cpu_id->driver_data == BAYTRAIL) + irq_chip = &int0002_byt_irqchip; + else + irq_chip = &int0002_cht_irqchip; + + ret = gpiochip_irqchip_add(chip, irq_chip, 0, handle_edge_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "Error adding irqchip: %d\n", ret); return ret; } - gpiochip_set_chained_irqchip(chip, &int0002_irqchip, irq, NULL); + gpiochip_set_chained_irqchip(chip, irq_chip, irq, NULL); return 0; } diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index 22dbf115782e..f2c621b55f49 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -15,6 +15,7 @@ #include <linux/bitfield.h> #include <linux/debugfs.h> #include <linux/delay.h> +#include <linux/dmi.h> #include <linux/io.h> #include <linux/module.h> #include <linux/pci.h> @@ -22,14 +23,24 @@ #include <asm/cpu_device_id.h> #include <asm/intel-family.h> +#include <asm/msr.h> #include "intel_pmc_core.h" -#define ICPU(model, data) \ - { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (kernel_ulong_t)data } - static struct pmc_dev pmc; +/* PKGC MSRs are common across Intel Core SoCs */ +static 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}, + {"Package C7", MSR_PKG_C7_RESIDENCY}, + {"Package C8", MSR_PKG_C8_RESIDENCY}, + {"Package C9", MSR_PKG_C9_RESIDENCY}, + {"Package C10", MSR_PKG_C10_RESIDENCY}, + {} +}; + 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}, @@ -108,6 +119,7 @@ static const struct pmc_bit_map spt_ltr_show_map[] = { {"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}, @@ -131,6 +143,7 @@ static const struct pmc_reg_map spt_reg_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, .ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET, .regmap_length = SPT_PMC_MMIO_REG_LEN, @@ -139,6 +152,7 @@ static const struct pmc_reg_map spt_reg_map = { .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, }; /* Cannonlake: PGD PFET Enable Ack Status Register(s) bitmap */ @@ -168,25 +182,26 @@ static const struct pmc_bit_map cnp_pfear_map[] = { {"SDX", BIT(4)}, {"SPE", BIT(5)}, {"Fuse", BIT(6)}, - {"Res_23", BIT(7)}, + /* Reserved for Cannonlake but valid for Icelake */ + {"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_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)}, + {"CSME_SMS2", BIT(4)}, + {"CSME_SMS1", BIT(5)}, + {"CSME_RTC", BIT(6)}, + {"CSME_PSF", BIT(7)}, {"SBR0", BIT(0)}, {"SBR1", BIT(1)}, @@ -203,7 +218,7 @@ static const struct pmc_bit_map cnp_pfear_map[] = { {"CNVI", BIT(3)}, {"UFS0", BIT(4)}, {"EMMC", BIT(5)}, - {"Res_6", BIT(6)}, + {"SPF", BIT(6)}, {"SBR6", BIT(7)}, {"SBR7", BIT(0)}, @@ -211,6 +226,20 @@ static const struct pmc_bit_map cnp_pfear_map[] = { {"HDA_PGD4", BIT(2)}, {"HDA_PGD5", BIT(3)}, {"HDA_PGD6", BIT(4)}, + /* Reserved for Cannonlake but valid for Icelake */ + {"PSF6", BIT(5)}, + {"PSF7", BIT(6)}, + {"PSF8", BIT(7)}, + + /* Icelake generation onwards only */ + {"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)}, {} }; @@ -276,6 +305,7 @@ static const struct pmc_bit_map cnp_ltr_show_map[] = { {"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}, @@ -291,6 +321,8 @@ static const struct pmc_bit_map cnp_ltr_show_map[] = { {"ISH", CNP_PMC_LTR_ISH}, {"UFSX2", CNP_PMC_LTR_UFSX2}, {"EMMC", CNP_PMC_LTR_EMMC}, + /* Reserved for Cannonlake but valid for Icelake */ + {"WIGIG", ICL_PMC_LTR_WIGIG}, /* Below two cannot be used for LTR_IGNORE */ {"CURRENT_PLATFORM", CNP_PMC_LTR_CUR_PLT}, {"AGGREGATED_SYSTEM", CNP_PMC_LTR_CUR_ASLT}, @@ -302,6 +334,7 @@ static const struct pmc_reg_map cnp_reg_map = { .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, .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, @@ -312,6 +345,22 @@ static const struct pmc_reg_map cnp_reg_map = { .ltr_ignore_max = CNP_NUM_IP_IGN_ALLOWED, }; +static const struct pmc_reg_map icl_reg_map = { + .pfear_sts = cnp_pfear_map, + .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, + .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, +}; + static inline u8 pmc_core_reg_read_byte(struct pmc_dev *pmcdev, int offset) { return readb(pmcdev->regbase + offset); @@ -328,9 +377,9 @@ static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int writel(val, pmcdev->regbase + reg_offset); } -static inline u32 pmc_core_adjust_slp_s0_step(u32 value) +static inline u64 pmc_core_adjust_slp_s0_step(u32 value) { - return value * SPT_PMC_SLP_S0_RES_COUNTER_STEP; + return (u64)value * SPT_PMC_SLP_S0_RES_COUNTER_STEP; } static int pmc_core_dev_state_get(void *data, u64 *val) @@ -380,7 +429,8 @@ static int pmc_core_ppfear_show(struct seq_file *s, void *unused) index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter); - for (index = 0; map[index].name; index++) + for (index = 0; map[index].name && + index < pmcdev->map->ppfear_buckets * 8; index++) pmc_core_display_map(s, index, pf_regs[index / 8], map); return 0; @@ -677,6 +727,25 @@ static int pmc_core_ltr_show(struct seq_file *s, void *unused) } DEFINE_SHOW_ATTRIBUTE(pmc_core_ltr); +static int pmc_core_pkgc_show(struct seq_file *s, void *unused) +{ + struct pmc_dev *pmcdev = s->private; + const struct pmc_bit_map *map = pmcdev->map->msr_sts; + u64 pcstate_count; + int index; + + for (index = 0; map[index].name ; index++) { + if (rdmsrl_safe(map[index].bit_mask, &pcstate_count)) + continue; + + seq_printf(s, "%-8s : 0x%llx\n", map[index].name, + pcstate_count); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(pmc_core_pkgc); + static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) { debugfs_remove_recursive(pmcdev->dbgfs_dir); @@ -701,7 +770,10 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev) debugfs_create_file("ltr_ignore", 0644, dir, pmcdev, &pmc_core_ltr_ignore_ops); - debugfs_create_file("ltr_show", 0644, dir, pmcdev, &pmc_core_ltr_fops); + debugfs_create_file("ltr_show", 0444, dir, pmcdev, &pmc_core_ltr_fops); + + debugfs_create_file("package_cstate_show", 0444, dir, pmcdev, + &pmc_core_pkgc_fops); if (pmcdev->map->pll_sts) debugfs_create_file("pll_status", 0444, dir, pmcdev, @@ -735,11 +807,12 @@ static inline void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) #endif /* CONFIG_DEBUG_FS */ static const struct x86_cpu_id intel_pmc_core_ids[] = { - ICPU(INTEL_FAM6_SKYLAKE_MOBILE, &spt_reg_map), - ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, &spt_reg_map), - ICPU(INTEL_FAM6_KABYLAKE_MOBILE, &spt_reg_map), - ICPU(INTEL_FAM6_KABYLAKE_DESKTOP, &spt_reg_map), - ICPU(INTEL_FAM6_CANNONLAKE_MOBILE, &cnp_reg_map), + INTEL_CPU_FAM6(SKYLAKE_MOBILE, spt_reg_map), + INTEL_CPU_FAM6(SKYLAKE_DESKTOP, spt_reg_map), + INTEL_CPU_FAM6(KABYLAKE_MOBILE, spt_reg_map), + INTEL_CPU_FAM6(KABYLAKE_DESKTOP, spt_reg_map), + INTEL_CPU_FAM6(CANNONLAKE_MOBILE, cnp_reg_map), + INTEL_CPU_FAM6(ICELAKE_MOBILE, icl_reg_map), {} }; @@ -750,6 +823,37 @@ static const struct pci_device_id pmc_pci_ids[] = { { 0, }, }; +/* + * This quirk can be used on those platforms where + * the platform BIOS enforces 24Mhx Crystal to shutdown + * before PMC can assert SLP_S0#. + */ +int quirk_xtal_ignore(const struct dmi_system_id *id) +{ + struct pmc_dev *pmcdev = &pmc; + u32 value; + + value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_vric1_offset); + /* 24MHz Crystal Shutdown Qualification Disable */ + value |= SPT_PMC_VRIC1_XTALSDQDIS; + /* Low Voltage Mode Enable */ + value &= ~SPT_PMC_VRIC1_SLPS0LVEN; + pmc_core_reg_write(pmcdev, pmcdev->map->pm_vric1_offset, value); + return 0; +} + +static const struct dmi_system_id pmc_core_dmi_table[] = { + { + .callback = quirk_xtal_ignore, + .ident = "HP Elite x2 1013 G3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite x2 1013 G3"), + }, + }, + {} +}; + static int __init pmc_core_probe(void) { struct pmc_dev *pmcdev = &pmc; @@ -768,7 +872,7 @@ static int __init pmc_core_probe(void) * Sunrisepoint PCH regmap can't be used. Use Cannonlake PCH regmap * in this case. */ - if (!pci_dev_present(pmc_pci_ids)) + if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids)) pmcdev->map = &cnp_reg_map; if (lpit_read_residency_count_address(&slp_s0_addr)) @@ -791,6 +895,7 @@ static int __init pmc_core_probe(void) return err; } + dmi_check_system(pmc_core_dmi_table); pr_info(" initialized\n"); return 0; } diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h index 89554cba5758..88d9c0653a5f 100644 --- a/drivers/platform/x86/intel_pmc_core.h +++ b/drivers/platform/x86/intel_pmc_core.h @@ -25,6 +25,7 @@ #define SPT_PMC_MTPMC_OFFSET 0x20 #define SPT_PMC_MFPMC_OFFSET 0x38 #define SPT_PMC_LTR_IGNORE_OFFSET 0x30C +#define SPT_PMC_VRIC1_OFFSET 0x31c #define SPT_PMC_MPHY_CORE_STS_0 0x1143 #define SPT_PMC_MPHY_CORE_STS_1 0x1142 #define SPT_PMC_MPHY_COM_STS_0 0x1155 @@ -32,7 +33,7 @@ #define SPT_PMC_SLP_S0_RES_COUNTER_STEP 0x64 #define PMC_BASE_ADDR_MASK ~(SPT_PMC_MMIO_REG_LEN - 1) #define MTPMC_MASK 0xffff0000 -#define PPFEAR_MAX_NUM_ENTRIES 5 +#define PPFEAR_MAX_NUM_ENTRIES 12 #define SPT_PPFEAR_NUM_ENTRIES 5 #define SPT_PMC_READ_DISABLE_BIT 0x16 #define SPT_PMC_MSG_FULL_STS_BIT 0x18 @@ -46,6 +47,7 @@ #define SPT_PMC_LTR_SATA 0x368 #define SPT_PMC_LTR_GBE 0x36C #define SPT_PMC_LTR_XHCI 0x370 +#define SPT_PMC_LTR_RESERVED 0x374 #define SPT_PMC_LTR_ME 0x378 #define SPT_PMC_LTR_EVA 0x37C #define SPT_PMC_LTR_SPC 0x380 @@ -135,6 +137,9 @@ enum ppfear_regs { #define SPT_PMC_BIT_MPHY_CMN_LANE2 BIT(2) #define SPT_PMC_BIT_MPHY_CMN_LANE3 BIT(3) +#define SPT_PMC_VRIC1_SLPS0LVEN BIT(13) +#define SPT_PMC_VRIC1_XTALSDQDIS BIT(22) + /* Cannonlake Power Management Controller register offsets */ #define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4 #define CNP_PMC_PM_CFG_OFFSET 0x1818 @@ -156,6 +161,7 @@ enum ppfear_regs { #define CNP_PMC_LTR_SATA 0x1B68 #define CNP_PMC_LTR_GBE 0x1B6C #define CNP_PMC_LTR_XHCI 0x1B70 +#define CNP_PMC_LTR_RESERVED 0x1B74 #define CNP_PMC_LTR_ME 0x1B78 #define CNP_PMC_LTR_EVA 0x1B7C #define CNP_PMC_LTR_SPC 0x1B80 @@ -176,6 +182,10 @@ enum ppfear_regs { #define LTR_REQ_SNOOP BIT(15) #define LTR_REQ_NONSNOOP BIT(31) +#define ICL_PPFEAR_NUM_ENTRIES 9 +#define ICL_NUM_IP_IGN_ALLOWED 20 +#define ICL_PMC_LTR_WIGIG 0x1BFC + struct pmc_bit_map { const char *name; u32 bit_mask; @@ -208,6 +218,7 @@ struct pmc_reg_map { const struct pmc_bit_map *pll_sts; const struct pmc_bit_map **slps0_dbg_maps; const struct pmc_bit_map *ltr_show_sts; + const struct pmc_bit_map *msr_sts; const u32 slp_s0_offset; const u32 ltr_ignore_offset; const int regmap_length; @@ -217,6 +228,7 @@ struct pmc_reg_map { const int pm_read_disable_bit; const u32 slps0_dbg_offset; const u32 ltr_ignore_max; + const u32 pm_vric1_offset; }; /** diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index df3fcd36776a..48fa7573e29b 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -25,6 +25,7 @@ #define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00 #define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 #define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02 +#define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03 #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e #define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f @@ -33,6 +34,7 @@ #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 #define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23 #define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24 +#define MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION 0x2a #define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30 #define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET 0x31 #define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET 0x32 @@ -67,6 +69,9 @@ #define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xee #define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xef #define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xf0 +#define MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET 0xf5 +#define MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET 0xf6 +#define MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET 0xf7 #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda @@ -584,36 +589,48 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = { .label = "fan1", .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, .mask = BIT(0), + .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET, + .bit = BIT(0), .hpdev.nr = MLXPLAT_CPLD_NR_NONE, }, { .label = "fan2", .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, .mask = BIT(1), + .capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CA |