Commit dbbdf54c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'platform-drivers-x86-v5.1-1' of git://git.infradead.org/linux-platform-drivers-x86

Pull x86 platform driver updates from Darren Hart:

 - use MODULE_DEVICE_TABLE across several wmi drivers, keeping
   wmi_device_id and MODULE_ALIAS() declarations in sync

 - add several Ideapad models to the no_hw_rfkill list

 - add support for new Mellanox platforms, including new fan and LED
   functionality

 - address Dell keyboard backlight change event and power button release
   issues

 - update dell_rbu to use appropriate memory allocation mechanisms

 - several small fixes and Ice Lake support for intel_pmc_core

 - fix a suspend regression for Cherry Trail based devices in
   intel_int0002_vgpio

 - a few other routine fixes

* tag 'platform-drivers-x86-v5.1-1' of git://git.infradead.org/linux-platform-drivers-x86: (50 commits)
  MAINTAINERS: Include mlxreg.h in Mellanox Platform Driver files
  platform/x86: ideapad-laptop: Add S130-14IGM to no_hw_rfkill list
  platform/x86: mlx-platform: Fix access mode for fan_dir attribute
  platform/x86: mlx-platform: Add UID LED for the next generation systems
  platform/x86: mlx-platform: Add extra CPLD for next generation systems
  platform/x86: wmi-bmof: use MODULE_DEVICE_TABLE() instead of MODULE_ALIAS()
  platform/x86: intel-wmi-thunderbolt: use MODULE_DEVICE_TABLE() instead of MODULE_ALIAS()
  platform/x86: huawei-wmi: use MODULE_DEVICE_TABLE() instead of MODULE_ALIAS()
  platform/x86: dell-wmi: use MODULE_DEVICE_TABLE() instead of MODULE_ALIAS()
  platform/x86: dell-wmi-descriptor: use MODULE_DEVICE_TABLE() instead of MODULE_ALIAS()
  platform/x86: dell-smbios-wmi: use MODULE_DEVICE_TABLE() instead of MODULE_ALIAS()
  platform/x86: wmi: add WMI support to MODULE_DEVICE_TABLE()
  platform/x86: wmi: move struct wmi_device_id to mod_devicetable.h
  modpost: file2alias: define size of alias
  platform/x86: touchscreen_dmi: Add info for the CHUWI Hi10 Air tablet
  platform/x86: ideapad-laptop: Add Ideapad 530S-14ARR to no_hw_rfkill list
  platform/x86: ideapad-laptop: Add Yoga C930 to no_hw_rfkill_list
  platform/x86: intel_pmc_core: Quirk to ignore XTAL shutdown
  platform/x86: intel_pmc_core: Add Package cstates residency info
  platform/x86: intel_pmc_core: Add ICL platform support
  ...
parents 45ba8d5d 9c22cc02
......@@ -21,7 +21,19 @@ Description: These files show with which CPLD versions have been burned
The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
cpld3_version
fan_dir
Date: December 2018
KernelVersion: 5.0
Contact: Vadim Pasternak <vadimpmellanox.com>
Description: This file shows the system fans direction:
forward direction - relevant bit is set 0;
reversed direction - relevant bit is set 1.
The files are read only.
What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
jtag_enable
Date: November 2018
KernelVersion: 5.0
......
......@@ -9900,6 +9900,7 @@ M: Vadim Pasternak <vadimp@mellanox.com>
L: platform-driver-x86@vger.kernel.org
S: Supported
F: drivers/platform/mellanox/
F: include/linux/platform_data/mlxreg.h
MELLANOX MLX4 core VPI driver
M: Tariq Toukan <tariqt@mellanox.com>
......
......@@ -1545,6 +1545,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
*/
static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
{"BSG1160", },
{"BSG2150", },
{"INT33FE", },
{"INT3515", },
{}
......
......@@ -22,6 +22,7 @@
#define MLXREG_LED_AMBER_SOLID 0x09 /* Solid amber */
#define MLXREG_LED_BLINK_3HZ 167 /* ~167 msec off/on - HW support */
#define MLXREG_LED_BLINK_6HZ 83 /* ~83 msec off/on - HW support */
#define MLXREG_LED_CAPABILITY_CLEAR GENMASK(31, 8) /* Clear mask */
/**
* struct mlxreg_led_data - led control data:
......@@ -187,6 +188,7 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv)
struct mlxreg_led_data *led_data;
struct led_classdev *led_cdev;
enum led_brightness brightness;
u32 regval;
int i;
int err;
......@@ -196,6 +198,23 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv)
if (!led_data)
return -ENOMEM;
if (data->capability) {
err = regmap_read(led_pdata->regmap, data->capability,
&regval);
if (err) {
dev_err(&priv->pdev->dev, "Failed to query capability register\n");
return err;
}
if (!(regval & data->bit))
continue;
/*
* Field "bit" can contain one capability bit in 0 byte
* and offset bit in 1-3 bytes. Clear capability bit and
* keep only offset bit.
*/
data->bit &= MLXREG_LED_CAPABILITY_CLEAR;
}
led_cdev = &led_data->led_cdev;
led_data->data_parent = priv;
if (strstr(data->label, "red") ||
......
......@@ -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, &regval);
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;
......
......@@ -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;
}
......
......@@ -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);
......@@ -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");
......@@ -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);
......@@ -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,10 +378,6 @@ 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);
......@@ -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) {
pr_debug("Not enough memory for image update:"
"size = %ld\n", size);
return -ENOMEM;
}
spin_lock(&rbu_data.lock);
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 */
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.bios_image_size = rbu_data.image_update_buffer_size;
rbu_data.image_update_ordernum = ordernum;
rbu_data.dma_alloc = dma_alloc;
rc = 0;
} else {
pr_debug("Not enough memory for image update:"
"size = %ld\n", size);
rc = -ENOMEM;
}
return rc;
return 0;
}
static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
......
......@@ -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");
......@@ -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 },
{ }
};
......
......@@ -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"),
},
},
{
......@@ -1090,6 +1090,27 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15ISK"),
},
},
{
.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 = {
......@@ -1153,6 +1174,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion Y530-15ICH"),
},
},
{
.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 = {
......@@ -1244,6 +1272,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920-13IKB"),
},
},
{
.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 = {
......
......@@ -363,7 +363,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
* 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,9 +372,12 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
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 */
if (event != 0xc0) {
......
......@@ -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");
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
};
/**
......
......@@ -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_CAP_OFFSET,
.bit = BIT(1),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
{
.label = "fan3",
.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
.mask = BIT(2),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(2),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
{
.label = "fan4",
.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
.mask = BIT(3),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(3),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
{
.label = "fan5",
.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
.mask = BIT(4),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(4),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
{
.label = "fan6",
.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
.mask = BIT(5),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(5),
.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
},
};
......@@ -816,61 +833,90 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
.label = "fan1:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(0),
},
{
.label = "fan1:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(0),
},
{
.label = "fan2:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(1),
},
{
.label = "fan2:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(1),
},
{
.label = "fan3:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(2),
},
{
.label = "fan3:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(2),
},
{
.label = "fan4:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(3),
},
{
.label = "fan4:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(3),
},
{
.label = "fan5:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(4),
},
{
.label = "fan5:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(4),
},
{
.label = "fan6:green",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(5),
},
{
.label = "fan6:orange",
.reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
.mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
.bit = BIT(5),
},
{
.label = "uid:blue",
.reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
.mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
},
};
......@@ -1099,6 +1145,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
.bit = GENMASK(7, 0),
.mode = 0444,
},
{
.label = "cpld4_version",
.reg = MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET,
.bit = GENMASK(7, 0),
.mode = 0444,
},
{
.label = "reset_long_pb",
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
......@@ -1184,6 +1236,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
.bit = 1,
.mode = 0444,
},
{
.label = "fan_dir",
.reg = MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION,
.bit = GENMASK(7, 0),
.mode = 0444,
},
};
static struct mlxreg_core_platform_data mlxplat_default_ng_regs_io_data = {
......@@ -1201,61 +1259,85 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
.label = "tacho1",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(0),
},
{
.label = "tacho2",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(1),
},
{
.label = "tacho3",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(2),
},
{
.label = "tacho4",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(3),
},
{
.label = "tacho5",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(4),
},
{
.label = "tacho6",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(5),
},
{
.label = "tacho7",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(6),
},
{
.label = "tacho8",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET,
.bit = BIT(7),
},
{
.label = "tacho9",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
.bit = BIT(0),
},
{
.label = "tacho10",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
.bit = BIT(1),
},
{
.label = "tacho11",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
.bit = BIT(2),
},
{
.label = "tacho12",
.reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET,
.mask = GENMASK(7, 0),
.capability = MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET,
.bit = BIT(3),
},
};
......@@ -1299,6 +1381,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
......@@ -1307,6 +1390,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION:
case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
......@@ -1341,6 +1425,9 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET:
return true;
}
return false;
......@@ -1352,6 +1439,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
......@@ -1360,6 +1448,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION:
case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
......@@ -1392,6 +1481,9 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_CAP1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_CAP2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET:
return true;
}
return false;
......@@ -1613,6 +1705,13 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "MSN34"),
},
},
{
.callback = mlxplat_dmi_qmb7xx_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "MSN38"),
},
},
{
.callback = mlxplat_dmi_default_matched,
.matches = {
......@@ -1643,6 +1742,12 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"),
},
},
{
.callback = mlxplat_dmi_qmb7xx_matched,
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "VMOD0007"),
},
},
{ }
};
......
......@@ -41,6 +41,20 @@ static const struct ts_dmi_data chuwi_hi8_data = {
.properties = chuwi_hi8_props,
};
static const struct property_entry chuwi_hi8_air_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-hi8-air.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
{ }
};
static const struct ts_dmi_data chuwi_hi8_air_data = {
.acpi_name = "MSSL1680:00",
.properties = chuwi_hi8_air_props,
};
static const struct property_entry chuwi_hi8_pro_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 6),
PROPERTY_ENTRY_U32("touchscreen-min-y", 3),
......@@ -58,6 +72,25 @@ static const struct ts_dmi_data chuwi_hi8_pro_data = {
.properties = chuwi_hi8_pro_props,
};
static const struct property_entry chuwi_hi10_air_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1981),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1271),
PROPERTY_ENTRY_U32("touchscreen-min-x", 99),
PROPERTY_ENTRY_U32("touchscreen-min-y", 9),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_U32("touchscreen-fuzz-x", 5),
PROPERTY_ENTRY_U32("touchscreen-fuzz-y", 4),
PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi10-air.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
static const struct ts_dmi_data chuwi_hi10_air_data = {
.acpi_name = "MSSL1680:00",
.properties = chuwi_hi10_air_props,
};
static const struct property_entry chuwi_vi8_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 4),
PROPERTY_ENTRY_U32("touchscreen-min-y", 6),
......@@ -369,6 +402,24 @@ static const struct ts_dmi_data pov_mobii_wintab_p800w_v21_data = {
.properties = pov_mobii_wintab_p800w_v21_props,
};
static const struct property_entry pov_mobii_wintab_p1006w_v10_props[] = {
PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
PROPERTY_ENTRY_U32("touchscreen-min-y", 3),
PROPERTY_ENTRY_U32("touchscreen-size-x", 1984),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1520),
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
PROPERTY_ENTRY_STRING("firmware-name",
"gsl3692-pov-mobii-wintab-p1006w-v10.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
static const struct ts_dmi_data pov_mobii_wintab_p1006w_v10_data = {
.acpi_name = "MSSL1680:00",
.properties = pov_mobii_wintab_p1006w_v10_props,
};
static const struct property_entry teclast_x3_plus_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
......@@ -497,6 +548,15 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
},
},
{
/* Chuwi Hi8 Air (CWI543) */
.driver_data = (void *)&chuwi_hi8_air_data,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Default string"),
DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
DMI_MATCH(DMI_PRODUCT_NAME, "Hi8 Air"),
},
},
{
/* Chuwi Hi8 Pro (CWI513) */
.driver_data = (void *)&chuwi_hi8_pro_data,
......@@ -505,6 +565,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
},
},
{
/* Chuwi Hi10 Air */
.driver_data = (void *)&chuwi_hi10_air_data,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
DMI_MATCH(DMI_PRODUCT_SKU, "P1W6_C109D_B"),
},
},
{
/* Chuwi Vi8 (CWI506) */
.driver_data = (void *)&chuwi_vi8_data,
......@@ -706,6 +774,17 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
},
},
{
/* Point of View mobii wintab p1006w (v1.0) */
.driver_data = (void *)&pov_mobii_wintab_p1006w_v10_data,
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
/* Note 105b is Foxcon's USB/PCI vendor id */
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "105B"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"),
},
},
{
/* Teclast X3 Plus */
.driver_data = (void *)&teclast_x3_plus_data,
......
......@@ -119,7 +119,7 @@ static struct wmi_driver wmi_bmof_driver = {
module_wmi_driver(wmi_bmof_driver);
MODULE_ALIAS("wmi:" WMI_BMOF_GUID);
MODULE_DEVICE_TABLE(wmi, wmi_bmof_id_table);
MODULE_AUTHOR("Andrew Lutomirski <luto@kernel.org>");
MODULE_DESCRIPTION("WMI embedded Binary MOF driver");
MODULE_LICENSE("GPL");
......@@ -768,7 +768,10 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
struct wmi_block *wblock = dev_to_wblock(dev);
const struct wmi_device_id *id = wmi_driver->id_table;
while (id->guid_string) {
if (id == NULL)
return 0;
while (*id->guid_string) {
uuid_le driver_guid;
if (WARN_ON(uuid_le_to_bin(id->guid_string, &driver_guid)))
......
......@@ -788,4 +788,16 @@ struct tee_client_device_id {
uuid_t uuid;
};
/* WMI */
#define WMI_MODULE_PREFIX "wmi:"
/**
* struct wmi_device_id - WMI device identifier
* @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
*/
struct wmi_device_id {
const char guid_string[UUID_STRING_LEN+1];
};
#endif /* LINUX_MOD_DEVICETABLE_H */
......@@ -61,6 +61,7 @@ struct mlxreg_hotplug_device {
* @reg: attribute register;
* @mask: attribute access mask;
* @bit: attribute effective bit;
* @capability: attribute capability register;
* @mode: access mode;
* @np - pointer to node platform associated with attribute;
* @hpdev - hotplug device data;
......@@ -72,6 +73,7 @@ struct mlxreg_core_data {
u32 reg;
u32 mask;
u32 bit;
u32 capability;
umode_t mode;
struct device_node *np;
struct mlxreg_hotplug_device hpdev;
......@@ -107,9 +109,9 @@ struct mlxreg_core_item {
/**
* struct mlxreg_core_platform_data - platform data:
*
* @led_data: led private data;
* @data: instance private data;
* @regmap: register map of parent device;
* @counter: number of led instances;
* @counter: number of instances;
*/
struct mlxreg_core_platform_data {
struct mlxreg_core_data *data;
......
......@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/acpi.h>
#include <linux/mod_devicetable.h>
#include <uapi/linux/wmi.h>
struct wmi_device {
......@@ -39,10 +40,6 @@ extern union acpi_object *wmidev_block_query(struct wmi_device *wdev,
extern int set_required_buffer_size(struct wmi_device *wdev, u64 length);
struct wmi_device_id {
const char *guid_string;
};
struct wmi_driver {
struct device_driver driver;
const struct wmi_device_id *id_table;
......
......@@ -228,5 +228,8 @@ int main(void)
DEVID(tee_client_device_id);
DEVID_FIELD(tee_client_device_id, uuid);
DEVID(wmi_device_id);
DEVID_FIELD(wmi_device_id, guid_string);
return 0;
}
......@@ -40,6 +40,7 @@ typedef struct {
typedef struct {
__u8 b[16];
} uuid_t;
#define UUID_STRING_LEN 36
/* Big exception to the "don't include kernel headers into userspace, which
* even potentially has different endianness and word sizes, since
......@@ -53,6 +54,9 @@ struct devtable {
int (*do_entry)(const char *filename, void *symval, char *alias);
};
/* Size of alias provided to do_entry functions */
#define ALIAS_SIZE 500
/* Define a variable f that holds the value of field f of struct devid
* based at address m.
*/
......@@ -1305,6 +1309,27 @@ static int do_tee_entry(const char *filename, void *symval, char *alias)
return 1;
}
/* Looks like: wmi:guid */
static int do_wmi_entry(const char *filename, void *symval, char *alias)
{
int len;
DEF_FIELD_ADDR(symval, wmi_device_id, guid_string);
if (strlen(*guid_string) != UUID_STRING_LEN) {
warn("Invalid WMI device id 'wmi:%s' in '%s'\n",
*guid_string, filename);
return 0;
}
len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string);
if (len < 0 || len >= ALIAS_SIZE) {
warn("Could not generate all MODULE_ALIAS's in '%s'\n",
filename);
return 0;
}
return 1;
}
/* Does namelen bytes of name exactly match the symbol? */
static bool sym_is(const char *name, unsigned namelen, const char *symbol)
{
......@@ -1321,7 +1346,7 @@ static void do_table(void *symval, unsigned long size,
struct module *mod)
{
unsigned int i;
char alias[500];
char alias[ALIAS_SIZE];
device_id_check(mod->name, device_id, size, id_size, symval);
/* Leave last one: it's the terminator. */
......@@ -1376,6 +1401,7 @@ static const struct devtable devtable[] = {
{"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
{"typec", SIZE_typec_device_id, do_typec_entry},
{"tee", SIZE_tee_client_device_id, do_tee_entry},
{"wmi", SIZE_wmi_device_id, do_wmi_entry},
};
/* Create MODULE_ALIAS() statements.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment