Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Pull x86 platform driver updates from Andy Shevchenko:

- The driver for Silead touchscreen configurations has been renamed
from silead_dmi to touchscreen_dmi since it starts supporting other
touchscreens which require some DMI quirks

It also gets expanded to cover cases for Chuwi Vi10, ONDA V891W,
Connect Tablet 9, Onda V820w, and Cube KNote i1101 tablets.

- Another bunch of changes is related to Mellanox platform code to
allow user space to communicate with Mellanox for system control and
monitoring purposes. The driver notifies user on hotplug device
signal receiving.

- ASUS WMI drivers recognize lid flip action on UX360, and correctly
toggles airplane mode LED. In addition the keyboard backlight toggle
gets support.

- ThinkPad ACPI driver enables support for calculator key (on at least
P52). It also has been fixed to support three characters model
designators, which are used for modern laptops. Earlier the battery,
marked as BAT1, on ThinkPad laptops has not been configured properly,
which is fixed. On the opposite the multi-battery configurations now
probed correctly.

- Dell SMBIOS driver starts working on some Dell servers which do not
support token interface. The regression with backlight detection has
also been fixed. In order to support dock mode on some laptops, Intel
virtual button driver has been fixed. The last but not least is the
fix to Intel HID driver due to changes in Dell systems that prevented
to use power button.

* tag 'platform-drivers-x86-v4.19-1' of git://git.infradead.org/linux-platform-drivers-x86: (47 commits)
platform/x86: acer-wmi: Silence "unsupported" message a bit
platform/x86: intel_punit_ipc: fix build errors
platform/x86: ideapad: Add Y520-15IKBM and Y720-15IKBM to no_hw_rfkill
platform/x86: asus-nb-wmi: Add keymap entry for lid flip action on UX360
platform/x86: acer-wmi: refactor function has_cap
platform/x86: thinkpad_acpi: Fix multi-battery bug
platform/x86: thinkpad_acpi: extend battery quirk coverage
platform/x86: touchscreen_dmi: Add info for the Cube KNote i1101 tablet
platform/x86: mlx-platform: Fix copy-paste error in mlxplat_init()
platform/x86: mlx-platform: Remove unused define
platform/x86: mlx-platform: Change mlxreg-io configuration for MSN274x systems
Documentation/ABI: Add new attribute for mlxreg-io sysfs interfaces
platform/x86: mlx-platform: Allow mlxreg-io driver activation for more systems
platform/x86: mlx-platform: Add ASIC hotplug device configuration
platform/mellanox: mlxreg-hotplug: Add hotplug hwmon uevent notification
platform/mellanox: mlxreg-hotplug: Improve mechanism of ASIC health discovery
platform/x86: mlx-platform: Add mlxreg-fan platform driver activation
platform/x86: dell-laptop: Fix backlight detection
platform/x86: toshiba_acpi: Fix defined but not used build warnings
platform/x86: thinkpad_acpi: Support battery quirk
...

+2107 -788
+78
Documentation/ABI/stable/sysfs-driver-mlxreg-io
··· 1 + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ 2 + asic_health 3 + 4 + Date: June 2018 5 + KernelVersion: 4.19 6 + Contact: Vadim Pasternak <vadimpmellanox.com> 7 + Description: This file shows ASIC health status. The possible values are: 8 + 0 - health failed, 2 - health OK, 3 - ASIC in booting state. 9 + 10 + The files are read only. 11 + 12 + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ 13 + cpld1_version 14 + cpld2_version 15 + 16 + Date: June 2018 17 + KernelVersion: 4.19 18 + Contact: Vadim Pasternak <vadimpmellanox.com> 19 + Description: These files show with which CPLD versions have been burned 20 + on carrier and switch boards. 21 + 22 + The files are read only. 23 + 24 + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/select_iio 25 + Date: June 2018 26 + KernelVersion: 4.19 27 + Contact: Vadim Pasternak <vadimpmellanox.com> 28 + Description: This file allows iio devices selection. 29 + 30 + Attribute select_iio can be written with 0 or with 1. It 31 + selects which one of iio devices can be accessed. 32 + 33 + The file is read/write. 34 + 35 + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/psu1_on 36 + /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/psu2_on 37 + /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/pwr_cycle 38 + /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/pwr_down 39 + Date: June 2018 40 + KernelVersion: 4.19 41 + Contact: Vadim Pasternak <vadimpmellanox.com> 42 + Description: These files allow asserting system power cycling, switching 43 + power supply units on and off and system's main power domain 44 + shutdown. 45 + Expected behavior: 46 + When pwr_cycle is written 1: auxiliary power domain will go 47 + down and after short period (about 1 second) up. 48 + When psu1_on or psu2_on is written 1, related unit will be 49 + disconnected from the power source, when written 0 - connected. 50 + If both are written 1 - power supplies main power domain will 51 + go down. 52 + When pwr_down is written 1, system's main power domain will go 53 + down. 54 + 55 + The files are write only. 56 + 57 + What: /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/ 58 + reset_aux_pwr_or_ref 59 + reset_asic_thermal 60 + reset_hotswap_or_halt 61 + reset_hotswap_or_wd 62 + reset_fw_reset 63 + reset_long_pb 64 + reset_main_pwr_fail 65 + reset_short_pb 66 + reset_sw_reset 67 + Date: June 2018 68 + KernelVersion: 4.19 69 + Contact: Vadim Pasternak <vadimpmellanox.com> 70 + Description: These files show the system reset cause, as following: power 71 + auxiliary outage or power refresh, ASIC thermal shutdown, halt, 72 + hotswap, watchdog, firmware reset, long press power button, 73 + short press power button, software reset. Value 1 in file means 74 + this is reset cause, 0 - otherwise. Only one of the above 75 + causes could be 1 at the same time, representing only last 76 + reset cause. 77 + 78 + The files are read only.
+1 -1
MAINTAINERS
··· 13207 13207 L: platform-driver-x86@vger.kernel.org 13208 13208 S: Maintained 13209 13209 F: drivers/input/touchscreen/silead.c 13210 - F: drivers/platform/x86/silead_dmi.c 13210 + F: drivers/platform/x86/touchscreen_dmi.c 13211 13211 13212 13212 SILICON MOTION SM712 FRAME BUFFER DRIVER 13213 13213 M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+11
drivers/platform/mellanox/Kconfig
··· 23 23 This driver handles hot-plug events for the power suppliers, power 24 24 cables and fans on the wide range Mellanox IB and Ethernet systems. 25 25 26 + config MLXREG_IO 27 + tristate "Mellanox platform register access driver support" 28 + depends on REGMAP 29 + depends on HWMON 30 + help 31 + This driver allows access to Mellanox programmable device register 32 + space through sysfs interface. The sets of registers for sysfs access 33 + are defined per system type bases and include the registers related 34 + to system resets operation, system reset causes monitoring and some 35 + kinds of mux selection. 36 + 26 37 endif # MELLANOX_PLATFORM
+1
drivers/platform/mellanox/Makefile
··· 4 4 # Mellanox Platform-Specific Drivers 5 5 # 6 6 obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o 7 + obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o
+43 -17
drivers/platform/mellanox/mlxreg-hotplug.c
··· 50 50 #define MLXREG_HOTPLUG_MASK_OFF 2 51 51 #define MLXREG_HOTPLUG_AGGR_MASK_OFF 1 52 52 53 - /* ASIC health parameters. */ 54 - #define MLXREG_HOTPLUG_HEALTH_MASK 0x02 55 - #define MLXREG_HOTPLUG_RST_CNTR 3 53 + /* ASIC good health mask. */ 54 + #define MLXREG_HOTPLUG_GOOD_HEALTH_MASK 0x02 56 55 57 56 #define MLXREG_HOTPLUG_ATTRS_MAX 24 58 57 #define MLXREG_HOTPLUG_NOT_ASSERT 3 ··· 102 103 { 103 104 struct mlxreg_core_hotplug_platform_data *pdata; 104 105 106 + /* Notify user by sending hwmon uevent. */ 107 + kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); 108 + 105 109 /* 106 110 * Return if adapter number is negative. It could be in case hotplug 107 111 * event is not associated with hotplug device. ··· 136 134 return 0; 137 135 } 138 136 139 - static void mlxreg_hotplug_device_destroy(struct mlxreg_core_data *data) 137 + static void 138 + mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv, 139 + struct mlxreg_core_data *data) 140 140 { 141 + /* Notify user by sending hwmon uevent. */ 142 + kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); 143 + 141 144 if (data->hpdev.client) { 142 145 i2c_unregister_device(data->hpdev.client); 143 146 data->hpdev.client = NULL; ··· 285 278 data = item->data + bit; 286 279 if (regval & BIT(bit)) { 287 280 if (item->inversed) 288 - mlxreg_hotplug_device_destroy(data); 281 + mlxreg_hotplug_device_destroy(priv, data); 289 282 else 290 283 mlxreg_hotplug_device_create(priv, data); 291 284 } else { 292 285 if (item->inversed) 293 286 mlxreg_hotplug_device_create(priv, data); 294 287 else 295 - mlxreg_hotplug_device_destroy(data); 288 + mlxreg_hotplug_device_destroy(priv, data); 296 289 } 297 290 } 298 291 ··· 332 325 goto out; 333 326 334 327 regval &= data->mask; 335 - item->cache = regval; 336 - if (regval == MLXREG_HOTPLUG_HEALTH_MASK) { 337 - if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) || 338 - !priv->after_probe) { 328 + 329 + if (item->cache == regval) 330 + goto ack_event; 331 + 332 + /* 333 + * ASIC health indication is provided through two bits. Bits 334 + * value 0x2 indicates that ASIC reached the good health, value 335 + * 0x0 indicates ASIC the bad health or dormant state and value 336 + * 0x3 indicates the booting state. During ASIC reset it should 337 + * pass the following states: dormant -> booting -> good. 338 + */ 339 + if (regval == MLXREG_HOTPLUG_GOOD_HEALTH_MASK) { 340 + if (!data->attached) { 341 + /* 342 + * ASIC is in steady state. Connect associated 343 + * device, if configured. 344 + */ 339 345 mlxreg_hotplug_device_create(priv, data); 340 346 data->attached = true; 341 347 } 342 348 } else { 343 349 if (data->attached) { 344 - mlxreg_hotplug_device_destroy(data); 350 + /* 351 + * ASIC health is failed after ASIC has been 352 + * in steady state. Disconnect associated 353 + * device, if it has been connected. 354 + */ 355 + mlxreg_hotplug_device_destroy(priv, data); 345 356 data->attached = false; 346 357 data->health_cntr = 0; 347 358 } 348 359 } 349 - 360 + item->cache = regval; 361 + ack_event: 350 362 /* Acknowledge event. */ 351 363 ret = regmap_write(priv->regmap, data->reg + 352 364 MLXREG_HOTPLUG_EVENT_OFF, 0); ··· 577 551 /* Remove all the attached devices in group. */ 578 552 count = item->count; 579 553 for (j = 0; j < count; j++, data++) 580 - mlxreg_hotplug_device_destroy(data); 554 + mlxreg_hotplug_device_destroy(priv, data); 581 555 } 582 556 } 583 557 ··· 642 616 disable_irq(priv->irq); 643 617 spin_lock_init(&priv->lock); 644 618 INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler); 645 - /* Perform initial interrupts setup. */ 646 - mlxreg_hotplug_set_irq(priv); 647 - 648 - priv->after_probe = true; 649 619 dev_set_drvdata(&pdev->dev, priv); 650 620 651 621 err = mlxreg_hotplug_attr_init(priv); ··· 658 636 PTR_ERR(priv->hwmon)); 659 637 return PTR_ERR(priv->hwmon); 660 638 } 639 + 640 + /* Perform initial interrupts setup. */ 641 + mlxreg_hotplug_set_irq(priv); 642 + priv->after_probe = true; 661 643 662 644 return 0; 663 645 }
+245
drivers/platform/mellanox/mlxreg-io.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Mellanox register access driver 4 + * 5 + * Copyright (C) 2018 Mellanox Technologies 6 + * Copyright (C) 2018 Vadim Pasternak <vadimp@mellanox.com> 7 + */ 8 + 9 + #include <linux/bitops.h> 10 + #include <linux/device.h> 11 + #include <linux/hwmon.h> 12 + #include <linux/hwmon-sysfs.h> 13 + #include <linux/module.h> 14 + #include <linux/of_device.h> 15 + #include <linux/platform_data/mlxreg.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/regmap.h> 18 + 19 + /* Attribute parameters. */ 20 + #define MLXREG_IO_ATT_SIZE 10 21 + #define MLXREG_IO_ATT_NUM 48 22 + 23 + /** 24 + * struct mlxreg_io_priv_data - driver's private data: 25 + * 26 + * @pdev: platform device; 27 + * @pdata: platform data; 28 + * @hwmon: hwmon device; 29 + * @mlxreg_io_attr: sysfs attributes array; 30 + * @mlxreg_io_dev_attr: sysfs sensor device attribute array; 31 + * @group: sysfs attribute group; 32 + * @groups: list of sysfs attribute group for hwmon registration; 33 + */ 34 + struct mlxreg_io_priv_data { 35 + struct platform_device *pdev; 36 + struct mlxreg_core_platform_data *pdata; 37 + struct device *hwmon; 38 + struct attribute *mlxreg_io_attr[MLXREG_IO_ATT_NUM + 1]; 39 + struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM]; 40 + struct attribute_group group; 41 + const struct attribute_group *groups[2]; 42 + }; 43 + 44 + static int 45 + mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val, 46 + bool rw_flag, u32 *regval) 47 + { 48 + int ret; 49 + 50 + ret = regmap_read(regmap, data->reg, regval); 51 + if (ret) 52 + goto access_error; 53 + 54 + /* 55 + * There are three kinds of attributes: single bit, full register's 56 + * bits and bit sequence. For the first kind field mask indicates which 57 + * bits are not related and field bit is set zero. For the second kind 58 + * field mask is set to zero and field bit is set with all bits one. 59 + * No special handling for such kind of attributes - pass value as is. 60 + * For the third kind, field mask indicates which bits are related and 61 + * field bit is set to the first bit number (from 1 to 32) is the bit 62 + * sequence. 63 + */ 64 + if (!data->bit) { 65 + /* Single bit. */ 66 + if (rw_flag) { 67 + /* For show: expose effective bit value as 0 or 1. */ 68 + *regval = !!(*regval & ~data->mask); 69 + } else { 70 + /* For store: set effective bit value. */ 71 + *regval &= data->mask; 72 + if (in_val) 73 + *regval |= ~data->mask; 74 + } 75 + } else if (data->mask) { 76 + /* Bit sequence. */ 77 + if (rw_flag) { 78 + /* For show: mask and shift right. */ 79 + *regval = ror32(*regval & data->mask, (data->bit - 1)); 80 + } else { 81 + /* For store: shift to the position and mask. */ 82 + in_val = rol32(in_val, data->bit - 1) & data->mask; 83 + /* Clear relevant bits and set them to new value. */ 84 + *regval = (*regval & ~data->mask) | in_val; 85 + } 86 + } 87 + 88 + access_error: 89 + return ret; 90 + } 91 + 92 + static ssize_t 93 + mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr, 94 + char *buf) 95 + { 96 + struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev); 97 + int index = to_sensor_dev_attr(attr)->index; 98 + struct mlxreg_core_data *data = priv->pdata->data + index; 99 + u32 regval = 0; 100 + int ret; 101 + 102 + ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, &regval); 103 + if (ret) 104 + goto access_error; 105 + 106 + return sprintf(buf, "%u\n", regval); 107 + 108 + access_error: 109 + return ret; 110 + } 111 + 112 + static ssize_t 113 + mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr, 114 + const char *buf, size_t len) 115 + { 116 + struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev); 117 + int index = to_sensor_dev_attr(attr)->index; 118 + struct mlxreg_core_data *data = priv->pdata->data + index; 119 + u32 input_val, regval; 120 + int ret; 121 + 122 + if (len > MLXREG_IO_ATT_SIZE) 123 + return -EINVAL; 124 + 125 + /* Convert buffer to input value. */ 126 + ret = kstrtou32(buf, len, &input_val); 127 + if (ret) 128 + return ret; 129 + 130 + ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false, 131 + &regval); 132 + if (ret) 133 + goto access_error; 134 + 135 + ret = regmap_write(priv->pdata->regmap, data->reg, regval); 136 + if (ret) 137 + goto access_error; 138 + 139 + return len; 140 + 141 + access_error: 142 + dev_err(&priv->pdev->dev, "Bus access error\n"); 143 + return ret; 144 + } 145 + 146 + static struct device_attribute mlxreg_io_devattr_rw = { 147 + .show = mlxreg_io_attr_show, 148 + .store = mlxreg_io_attr_store, 149 + }; 150 + 151 + static int mlxreg_io_attr_init(struct mlxreg_io_priv_data *priv) 152 + { 153 + int i; 154 + 155 + priv->group.attrs = devm_kcalloc(&priv->pdev->dev, 156 + priv->pdata->counter, 157 + sizeof(struct attribute *), 158 + GFP_KERNEL); 159 + if (!priv->group.attrs) 160 + return -ENOMEM; 161 + 162 + for (i = 0; i < priv->pdata->counter; i++) { 163 + priv->mlxreg_io_attr[i] = 164 + &priv->mlxreg_io_dev_attr[i].dev_attr.attr; 165 + memcpy(&priv->mlxreg_io_dev_attr[i].dev_attr, 166 + &mlxreg_io_devattr_rw, sizeof(struct device_attribute)); 167 + 168 + /* Set attribute name as a label. */ 169 + priv->mlxreg_io_attr[i]->name = 170 + devm_kasprintf(&priv->pdev->dev, GFP_KERNEL, 171 + priv->pdata->data[i].label); 172 + 173 + if (!priv->mlxreg_io_attr[i]->name) { 174 + dev_err(&priv->pdev->dev, "Memory allocation failed for sysfs attribute %d.\n", 175 + i + 1); 176 + return -ENOMEM; 177 + } 178 + 179 + priv->mlxreg_io_dev_attr[i].dev_attr.attr.mode = 180 + priv->pdata->data[i].mode; 181 + priv->mlxreg_io_dev_attr[i].dev_attr.attr.name = 182 + priv->mlxreg_io_attr[i]->name; 183 + priv->mlxreg_io_dev_attr[i].index = i; 184 + sysfs_attr_init(&priv->mlxreg_io_dev_attr[i].dev_attr.attr); 185 + } 186 + 187 + priv->group.attrs = priv->mlxreg_io_attr; 188 + priv->groups[0] = &priv->group; 189 + priv->groups[1] = NULL; 190 + 191 + return 0; 192 + } 193 + 194 + static int mlxreg_io_probe(struct platform_device *pdev) 195 + { 196 + struct mlxreg_io_priv_data *priv; 197 + int err; 198 + 199 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 200 + if (!priv) 201 + return -ENOMEM; 202 + 203 + priv->pdata = dev_get_platdata(&pdev->dev); 204 + if (!priv->pdata) { 205 + dev_err(&pdev->dev, "Failed to get platform data.\n"); 206 + return -EINVAL; 207 + } 208 + 209 + priv->pdev = pdev; 210 + 211 + err = mlxreg_io_attr_init(priv); 212 + if (err) { 213 + dev_err(&priv->pdev->dev, "Failed to allocate attributes: %d\n", 214 + err); 215 + return err; 216 + } 217 + 218 + priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, 219 + "mlxreg_io", 220 + priv, 221 + priv->groups); 222 + if (IS_ERR(priv->hwmon)) { 223 + dev_err(&pdev->dev, "Failed to register hwmon device %ld\n", 224 + PTR_ERR(priv->hwmon)); 225 + return PTR_ERR(priv->hwmon); 226 + } 227 + 228 + dev_set_drvdata(&pdev->dev, priv); 229 + 230 + return 0; 231 + } 232 + 233 + static struct platform_driver mlxreg_io_driver = { 234 + .driver = { 235 + .name = "mlxreg-io", 236 + }, 237 + .probe = mlxreg_io_probe, 238 + }; 239 + 240 + module_platform_driver(mlxreg_io_driver); 241 + 242 + MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>"); 243 + MODULE_DESCRIPTION("Mellanox regmap I/O access driver"); 244 + MODULE_LICENSE("GPL"); 245 + MODULE_ALIAS("platform:mlxreg-io");
+8 -8
drivers/platform/x86/Kconfig
··· 1196 1196 This driver is only required when the system is not using Hardware 1197 1197 P-States (HWP). In HWP mode, priority can be read from ACPI tables. 1198 1198 1199 - config SILEAD_DMI 1200 - bool "Tablets with Silead touchscreens" 1199 + config TOUCHSCREEN_DMI 1200 + bool "DMI based touchscreen configuration info" 1201 1201 depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD 1202 1202 ---help--- 1203 - Certain ACPI based tablets with Silead touchscreens do not have 1204 - enough data in ACPI tables for the touchscreen driver to handle 1205 - the touchscreen properly, as OEMs expected the data to be baked 1206 - into the tablet model specific version of the driver shipped 1207 - with the OS-image for the device. This option supplies the missing 1208 - information. Enable this for x86 tablets with Silead touchscreens. 1203 + Certain ACPI based tablets with e.g. Silead or Chipone touchscreens 1204 + do not have enough data in ACPI tables for the touchscreen driver to 1205 + handle the touchscreen properly, as OEMs expect the data to be baked 1206 + into the tablet model specific version of the driver shipped with the 1207 + the OS-image for the device. This option supplies the missing info. 1208 + Enable this for x86 tablets with Silead or Chipone touchscreens. 1209 1209 1210 1210 config INTEL_CHTDC_TI_PWRBTN 1211 1211 tristate "Intel Cherry Trail Dollar Cove TI power button driver"
+1 -1
drivers/platform/x86/Makefile
··· 78 78 obj-$(CONFIG_PVPANIC) += pvpanic.o 79 79 obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o 80 80 obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o 81 - obj-$(CONFIG_SILEAD_DMI) += silead_dmi.o 81 + obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o 82 82 obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o 83 83 obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o 84 84 obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
+2 -5
drivers/platform/x86/acer-wmi.c
··· 672 672 673 673 static bool has_cap(u32 cap) 674 674 { 675 - if ((interface->capability & cap) != 0) 676 - return 1; 677 - 678 - return 0; 675 + return interface->capability & cap; 679 676 } 680 677 681 678 /* ··· 2213 2216 if (wmi_has_guid(AMW0_GUID1) && 2214 2217 !dmi_check_system(amw0_whitelist) && 2215 2218 quirks == &quirk_unknown) { 2216 - pr_err("Unsupported machine has AMW0_GUID1, unable to load\n"); 2219 + pr_debug("Unsupported machine has AMW0_GUID1, unable to load\n"); 2217 2220 return -ENODEV; 2218 2221 } 2219 2222
+1
drivers/platform/x86/asus-nb-wmi.c
··· 496 496 { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, 497 497 { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, 498 498 { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ 499 + { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */ 499 500 { KE_END, 0}, 500 501 }; 501 502
+14 -10
drivers/platform/x86/asus-wireless.c
··· 52 52 }; 53 53 MODULE_DEVICE_TABLE(acpi, device_ids); 54 54 55 - static u64 asus_wireless_method(acpi_handle handle, const char *method, 56 - int param) 55 + static acpi_status asus_wireless_method(acpi_handle handle, const char *method, 56 + int param, u64 *ret) 57 57 { 58 58 struct acpi_object_list p; 59 59 union acpi_object obj; 60 60 acpi_status s; 61 - u64 ret; 62 61 63 62 acpi_handle_debug(handle, "Evaluating method %s, parameter %#x\n", 64 63 method, param); ··· 66 67 p.count = 1; 67 68 p.pointer = &obj; 68 69 69 - s = acpi_evaluate_integer(handle, (acpi_string) method, &p, &ret); 70 + s = acpi_evaluate_integer(handle, (acpi_string) method, &p, ret); 70 71 if (ACPI_FAILURE(s)) 71 72 acpi_handle_err(handle, 72 73 "Failed to eval method %s, param %#x (%d)\n", 73 74 method, param, s); 74 - acpi_handle_debug(handle, "%s returned %#llx\n", method, ret); 75 - return ret; 75 + else 76 + acpi_handle_debug(handle, "%s returned %#llx\n", method, *ret); 77 + 78 + return s; 76 79 } 77 80 78 81 static enum led_brightness led_state_get(struct led_classdev *led) 79 82 { 80 83 struct asus_wireless_data *data; 81 - int s; 84 + acpi_status s; 85 + u64 ret; 82 86 83 87 data = container_of(led, struct asus_wireless_data, led); 84 88 s = asus_wireless_method(acpi_device_handle(data->adev), "HSWC", 85 - data->hswc_params->status); 86 - if (s == data->hswc_params->on) 89 + data->hswc_params->status, &ret); 90 + if (ACPI_SUCCESS(s) && ret == data->hswc_params->on) 87 91 return LED_FULL; 88 92 return LED_OFF; 89 93 } ··· 94 92 static void led_state_update(struct work_struct *work) 95 93 { 96 94 struct asus_wireless_data *data; 95 + u64 ret; 97 96 98 97 data = container_of(work, struct asus_wireless_data, led_work); 99 98 asus_wireless_method(acpi_device_handle(data->adev), "HSWC", 100 - data->led_state); 99 + data->led_state, &ret); 101 100 } 102 101 103 102 static void led_state_set(struct led_classdev *led, enum led_brightness value) ··· 170 167 data->led.brightness_get = led_state_get; 171 168 data->led.flags = LED_CORE_SUSPENDRESUME; 172 169 data->led.max_brightness = 1; 170 + data->led.default_trigger = "rfkill-none"; 173 171 err = devm_led_classdev_register(&adev->dev, &data->led); 174 172 if (err) 175 173 destroy_workqueue(data->wq);
+30 -4
drivers/platform/x86/asus-wmi.c
··· 67 67 #define NOTIFY_BRNDOWN_MAX 0x2e 68 68 #define NOTIFY_KBD_BRTUP 0xc4 69 69 #define NOTIFY_KBD_BRTDWN 0xc5 70 + #define NOTIFY_KBD_BRTTOGGLE 0xc7 70 71 71 72 /* WMI Methods */ 72 73 #define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */ ··· 471 470 ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F); 472 471 473 472 asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL); 473 + led_classdev_notify_brightness_hw_changed(&asus->kbd_led, asus->kbd_led_wk); 474 474 } 475 475 476 476 static int kbd_led_read(struct asus_wmi *asus, int *level, int *env) ··· 502 500 return retval; 503 501 } 504 502 505 - static void kbd_led_set(struct led_classdev *led_cdev, 506 - enum led_brightness value) 503 + static void do_kbd_led_set(struct led_classdev *led_cdev, int value) 507 504 { 508 505 struct asus_wmi *asus; 506 + int max_level; 509 507 510 508 asus = container_of(led_cdev, struct asus_wmi, kbd_led); 509 + max_level = asus->kbd_led.max_brightness; 511 510 512 - if (value > asus->kbd_led.max_brightness) 513 - value = asus->kbd_led.max_brightness; 511 + if (value > max_level) 512 + value = max_level; 514 513 else if (value < 0) 515 514 value = 0; 516 515 517 516 asus->kbd_led_wk = value; 518 517 queue_work(asus->led_workqueue, &asus->kbd_led_work); 518 + } 519 + 520 + static void kbd_led_set(struct led_classdev *led_cdev, 521 + enum led_brightness value) 522 + { 523 + do_kbd_led_set(led_cdev, value); 519 524 } 520 525 521 526 static enum led_brightness kbd_led_get(struct led_classdev *led_cdev) ··· 675 666 676 667 asus->kbd_led_wk = led_val; 677 668 asus->kbd_led.name = "asus::kbd_backlight"; 669 + asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED; 678 670 asus->kbd_led.brightness_set = kbd_led_set; 679 671 asus->kbd_led.brightness_get = kbd_led_get; 680 672 asus->kbd_led.max_brightness = 3; ··· 1762 1752 asus_wmi_backlight_notify(asus, orig_code); 1763 1753 goto exit; 1764 1754 } 1755 + } 1756 + 1757 + if (code == NOTIFY_KBD_BRTUP) { 1758 + do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1); 1759 + goto exit; 1760 + } 1761 + if (code == NOTIFY_KBD_BRTDWN) { 1762 + do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk - 1); 1763 + goto exit; 1764 + } 1765 + if (code == NOTIFY_KBD_BRTTOGGLE) { 1766 + if (asus->kbd_led_wk == asus->kbd_led.max_brightness) 1767 + do_kbd_led_set(&asus->kbd_led, 0); 1768 + else 1769 + do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1); 1770 + goto exit; 1765 1771 } 1766 1772 1767 1773 if (is_display_toggle(code) &&
+21 -14
drivers/platform/x86/dell-smbios-base.c
··· 212 212 if ((buffer->cmd_class == CLASS_TOKEN_READ || 213 213 buffer->cmd_class == CLASS_TOKEN_WRITE) && 214 214 buffer->cmd_select < 3) { 215 + /* tokens enabled ? */ 216 + if (!da_tokens) { 217 + dev_dbg(d, "no token support on this system\n"); 218 + return -EINVAL; 219 + } 220 + 215 221 /* find the matching token ID */ 216 222 for (i = 0; i < da_num_tokens; i++) { 217 223 if (da_tokens[i].location != buffer->input[0]) ··· 320 314 struct calling_interface_token *dell_smbios_find_token(int tokenid) 321 315 { 322 316 int i; 317 + 318 + if (!da_tokens) 319 + return NULL; 323 320 324 321 for (i = 0; i < da_num_tokens; i++) { 325 322 if (da_tokens[i].tokenID == tokenid) ··· 574 565 575 566 dmi_walk(find_tokens, NULL); 576 567 577 - if (!da_tokens) { 578 - pr_info("Unable to find dmi tokens\n"); 579 - return -ENODEV; 580 - } 581 - 582 568 ret = platform_driver_register(&platform_driver); 583 569 if (ret) 584 570 goto fail_platform_driver; ··· 587 583 if (ret) 588 584 goto fail_platform_device_add; 589 585 590 - /* duplicate tokens will cause problems building sysfs files */ 591 - zero_duplicates(&platform_device->dev); 592 - 593 - ret = build_tokens_sysfs(platform_device); 594 - if (ret) 595 - goto fail_create_group; 596 - 597 586 /* register backends */ 598 587 wmi = init_dell_smbios_wmi(); 599 588 if (wmi) ··· 597 600 if (wmi && smm) { 598 601 pr_err("No SMBIOS backends available (wmi: %d, smm: %d)\n", 599 602 wmi, smm); 600 - goto fail_sysfs; 603 + goto fail_create_group; 604 + } 605 + 606 + if (da_tokens) { 607 + /* duplicate tokens will cause problems building sysfs files */ 608 + zero_duplicates(&platform_device->dev); 609 + 610 + ret = build_tokens_sysfs(platform_device); 611 + if (ret) 612 + goto fail_sysfs; 601 613 } 602 614 603 615 return 0; ··· 634 628 exit_dell_smbios_smm(); 635 629 mutex_lock(&smbios_mutex); 636 630 if (platform_device) { 637 - free_group(platform_device); 631 + if (da_tokens) 632 + free_group(platform_device); 638 633 platform_device_unregister(platform_device); 639 634 platform_driver_unregister(&platform_driver); 640 635 }
+2 -2
drivers/platform/x86/dell-smbios-smm.c
··· 24 24 static int da_command_address; 25 25 static int da_command_code; 26 26 static struct calling_interface_buffer *buffer; 27 - struct platform_device *platform_device; 27 + static struct platform_device *platform_device; 28 28 static DEFINE_MUTEX(smm_mutex); 29 29 30 30 static const struct dmi_system_id dell_device_table[] __initconst = { ··· 82 82 } 83 83 } 84 84 85 - int dell_smbios_smm_call(struct calling_interface_buffer *input) 85 + static int dell_smbios_smm_call(struct calling_interface_buffer *input) 86 86 { 87 87 struct smi_cmd command; 88 88 size_t size;
+1 -1
drivers/platform/x86/dell-smbios-wmi.c
··· 82 82 return 0; 83 83 } 84 84 85 - int dell_smbios_wmi_call(struct calling_interface_buffer *buffer) 85 + static int dell_smbios_wmi_call(struct calling_interface_buffer *buffer) 86 86 { 87 87 struct wmi_smbios_priv *priv; 88 88 size_t difference;
+16 -2
drivers/platform/x86/ideapad-laptop.c
··· 1133 1133 }, 1134 1134 }, 1135 1135 { 1136 - .ident = "Lenovo Legion Y520-15IKBN", 1136 + .ident = "Lenovo Legion Y520-15IKB", 1137 1137 .matches = { 1138 1138 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1139 - DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBN"), 1139 + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKB"), 1140 + }, 1141 + }, 1142 + { 1143 + .ident = "Lenovo Y520-15IKBM", 1144 + .matches = { 1145 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1146 + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBM"), 1140 1147 }, 1141 1148 }, 1142 1149 { ··· 1158 1151 .matches = { 1159 1152 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1160 1153 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBN"), 1154 + }, 1155 + }, 1156 + { 1157 + .ident = "Lenovo Y720-15IKBM", 1158 + .matches = { 1159 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 1160 + DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBM"), 1161 1161 }, 1162 1162 }, 1163 1163 {
+157 -21
drivers/platform/x86/intel-hid.c
··· 96 96 bool wakeup_mode; 97 97 }; 98 98 99 + #define HID_EVENT_FILTER_UUID "eeec56b3-4442-408f-a792-4edd4d758054" 100 + 101 + enum intel_hid_dsm_fn_codes { 102 + INTEL_HID_DSM_FN_INVALID, 103 + INTEL_HID_DSM_BTNL_FN, 104 + INTEL_HID_DSM_HDMM_FN, 105 + INTEL_HID_DSM_HDSM_FN, 106 + INTEL_HID_DSM_HDEM_FN, 107 + INTEL_HID_DSM_BTNS_FN, 108 + INTEL_HID_DSM_BTNE_FN, 109 + INTEL_HID_DSM_HEBC_V1_FN, 110 + INTEL_HID_DSM_VGBS_FN, 111 + INTEL_HID_DSM_HEBC_V2_FN, 112 + INTEL_HID_DSM_FN_MAX 113 + }; 114 + 115 + static const char *intel_hid_dsm_fn_to_method[INTEL_HID_DSM_FN_MAX] = { 116 + NULL, 117 + "BTNL", 118 + "HDMM", 119 + "HDSM", 120 + "HDEM", 121 + "BTNS", 122 + "BTNE", 123 + "HEBC", 124 + "VGBS", 125 + "HEBC" 126 + }; 127 + 128 + static unsigned long long intel_hid_dsm_fn_mask; 129 + static guid_t intel_dsm_guid; 130 + 131 + static bool intel_hid_execute_method(acpi_handle handle, 132 + enum intel_hid_dsm_fn_codes fn_index, 133 + unsigned long long arg) 134 + { 135 + union acpi_object *obj, argv4, req; 136 + acpi_status status; 137 + char *method_name; 138 + 139 + if (fn_index <= INTEL_HID_DSM_FN_INVALID || 140 + fn_index >= INTEL_HID_DSM_FN_MAX) 141 + return false; 142 + 143 + method_name = (char *)intel_hid_dsm_fn_to_method[fn_index]; 144 + 145 + if (!(intel_hid_dsm_fn_mask & fn_index)) 146 + goto skip_dsm_exec; 147 + 148 + /* All methods expects a package with one integer element */ 149 + req.type = ACPI_TYPE_INTEGER; 150 + req.integer.value = arg; 151 + 152 + argv4.type = ACPI_TYPE_PACKAGE; 153 + argv4.package.count = 1; 154 + argv4.package.elements = &req; 155 + 156 + obj = acpi_evaluate_dsm(handle, &intel_dsm_guid, 1, fn_index, &argv4); 157 + if (obj) { 158 + acpi_handle_debug(handle, "Exec DSM Fn code: %d[%s] success\n", 159 + fn_index, method_name); 160 + ACPI_FREE(obj); 161 + return true; 162 + } 163 + 164 + skip_dsm_exec: 165 + status = acpi_execute_simple_method(handle, method_name, arg); 166 + if (ACPI_SUCCESS(status)) 167 + return true; 168 + 169 + return false; 170 + } 171 + 172 + static bool intel_hid_evaluate_method(acpi_handle handle, 173 + enum intel_hid_dsm_fn_codes fn_index, 174 + unsigned long long *result) 175 + { 176 + union acpi_object *obj; 177 + acpi_status status; 178 + char *method_name; 179 + 180 + if (fn_index <= INTEL_HID_DSM_FN_INVALID || 181 + fn_index >= INTEL_HID_DSM_FN_MAX) 182 + return false; 183 + 184 + method_name = (char *)intel_hid_dsm_fn_to_method[fn_index]; 185 + 186 + if (!(intel_hid_dsm_fn_mask & fn_index)) 187 + goto skip_dsm_eval; 188 + 189 + obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid, 190 + 1, fn_index, 191 + NULL, ACPI_TYPE_INTEGER); 192 + if (obj) { 193 + *result = obj->integer.value; 194 + acpi_handle_debug(handle, 195 + "Eval DSM Fn code: %d[%s] results: 0x%llx\n", 196 + fn_index, method_name, *result); 197 + ACPI_FREE(obj); 198 + return true; 199 + } 200 + 201 + skip_dsm_eval: 202 + status = acpi_evaluate_integer(handle, method_name, NULL, result); 203 + if (ACPI_SUCCESS(status)) 204 + return true; 205 + 206 + return false; 207 + } 208 + 209 + static void intel_hid_init_dsm(acpi_handle handle) 210 + { 211 + union acpi_object *obj; 212 + 213 + guid_parse(HID_EVENT_FILTER_UUID, &intel_dsm_guid); 214 + 215 + obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid, 1, 0, NULL, 216 + ACPI_TYPE_BUFFER); 217 + if (obj) { 218 + intel_hid_dsm_fn_mask = *obj->buffer.pointer; 219 + ACPI_FREE(obj); 220 + } 221 + 222 + acpi_handle_debug(handle, "intel_hid_dsm_fn_mask = %llx\n", 223 + intel_hid_dsm_fn_mask); 224 + } 225 + 99 226 static int intel_hid_set_enable(struct device *device, bool enable) 100 227 { 101 - acpi_status status; 228 + acpi_handle handle = ACPI_HANDLE(device); 102 229 103 - status = acpi_execute_simple_method(ACPI_HANDLE(device), "HDSM", 104 - enable); 105 - if (ACPI_FAILURE(status)) { 230 + /* Enable|disable features - power button is always enabled */ 231 + if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN, 232 + enable)) { 106 233 dev_warn(device, "failed to %sable hotkeys\n", 107 234 enable ? "en" : "dis"); 108 235 return -EIO; ··· 256 129 } 257 130 258 131 /* Enable|disable features - power button is always enabled */ 259 - status = acpi_execute_simple_method(handle, "BTNE", 260 - enable ? button_cap : 1); 261 - if (ACPI_FAILURE(status)) 132 + if (!intel_hid_execute_method(handle, INTEL_HID_DSM_BTNE_FN, 133 + enable ? button_cap : 1)) 262 134 dev_warn(device, "failed to set button capability\n"); 263 135 } 264 136 ··· 343 217 struct platform_device *device = context; 344 218 struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); 345 219 unsigned long long ev_index; 346 - acpi_status status; 347 220 348 221 if (priv->wakeup_mode) { 349 222 /* ··· 394 269 return; 395 270 } 396 271 397 - status = acpi_evaluate_integer(handle, "HDEM", NULL, &ev_index); 398 - if (ACPI_FAILURE(status)) { 272 + if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDEM_FN, 273 + &ev_index)) { 399 274 dev_warn(&device->dev, "failed to get event index\n"); 400 275 return; 401 276 } ··· 409 284 { 410 285 acpi_handle handle = ACPI_HANDLE(&device->dev); 411 286 unsigned long long event_cap; 412 - acpi_status status; 413 - bool supported = false; 414 287 415 - status = acpi_evaluate_integer(handle, "HEBC", NULL, &event_cap); 416 - if (ACPI_SUCCESS(status) && (event_cap & 0x20000)) 417 - supported = true; 288 + if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V2_FN, 289 + &event_cap)) { 290 + /* Check presence of 5 button array or v2 power button */ 291 + if (event_cap & 0x60000) 292 + return true; 293 + } 294 + 295 + if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V1_FN, 296 + &event_cap)) { 297 + if (event_cap & 0x20000) 298 + return true; 299 + } 418 300 419 301 if (dmi_check_system(button_array_table)) 420 - supported = true; 302 + return true; 421 303 422 - return supported; 304 + return false; 423 305 } 424 306 425 307 static int intel_hid_probe(struct platform_device *device) ··· 437 305 acpi_status status; 438 306 int err; 439 307 440 - status = acpi_evaluate_integer(handle, "HDMM", NULL, &mode); 441 - if (ACPI_FAILURE(status)) { 308 + intel_hid_init_dsm(handle); 309 + 310 + if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDMM_FN, &mode)) { 442 311 dev_warn(&device->dev, "failed to read mode\n"); 443 312 return -ENODEV; 444 313 } ··· 485 352 goto err_remove_notify; 486 353 487 354 if (priv->array) { 355 + unsigned long long dummy; 356 + 488 357 intel_button_array_enable(&device->dev, true); 489 358 490 359 /* Call button load method to enable HID power button */ 491 - status = acpi_evaluate_object(handle, "BTNL", NULL, NULL); 492 - if (ACPI_FAILURE(status)) 360 + if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, 361 + &dummy)) { 493 362 dev_warn(&device->dev, 494 363 "failed to enable HID power button\n"); 364 + } 495 365 } 496 366 497 367 device_init_wakeup(&device->dev, true);
+5
drivers/platform/x86/intel-vbtn.c
··· 17 17 18 18 /* When NOT in tablet mode, VGBS returns with the flag 0x40 */ 19 19 #define TABLET_MODE_FLAG 0x40 20 + #define DOCK_MODE_FLAG 0x80 20 21 21 22 MODULE_LICENSE("GPL"); 22 23 MODULE_AUTHOR("AceLan Kao"); ··· 39 38 { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */ 40 39 { KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key press */ 41 40 { KE_KEY, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key release */ 41 + { KE_SW, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */ 42 + { KE_SW, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */ 42 43 { KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */ 43 44 { KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */ 44 45 { KE_END }, ··· 124 121 125 122 m = !(obj->integer.value & TABLET_MODE_FLAG); 126 123 input_report_switch(priv->input_dev, SW_TABLET_MODE, m); 124 + m = (obj->integer.value & DOCK_MODE_FLAG) ? 1 : 0; 125 + input_report_switch(priv->input_dev, SW_DOCK, m); 127 126 out: 128 127 kfree(vgbs_output.pointer); 129 128 }
+1 -4
drivers/platform/x86/intel_ips.c
··· 858 858 859 859 static u16 read_ptv(struct ips_driver *ips) 860 860 { 861 - u16 val, slope, offset; 862 - 863 - slope = (ips->pta_val & PTA_SLOPE_MASK) >> PTA_SLOPE_SHIFT; 864 - offset = ips->pta_val & PTA_OFFSET_MASK; 861 + u16 val; 865 862 866 863 val = thm_readw(THM_PTV) & PTV_MASK; 867 864
+120
drivers/platform/x86/intel_pmc_core.c
··· 196 196 {} 197 197 }; 198 198 199 + static const struct pmc_bit_map cnp_slps0_dbg0_map[] = { 200 + {"AUDIO_D3", BIT(0)}, 201 + {"OTG_D3", BIT(1)}, 202 + {"XHCI_D3", BIT(2)}, 203 + {"LPIO_D3", BIT(3)}, 204 + {"SDX_D3", BIT(4)}, 205 + {"SATA_D3", BIT(5)}, 206 + {"UFS0_D3", BIT(6)}, 207 + {"UFS1_D3", BIT(7)}, 208 + {"EMMC_D3", BIT(8)}, 209 + {} 210 + }; 211 + 212 + static const struct pmc_bit_map cnp_slps0_dbg1_map[] = { 213 + {"SDIO_PLL_OFF", BIT(0)}, 214 + {"USB2_PLL_OFF", BIT(1)}, 215 + {"AUDIO_PLL_OFF", BIT(2)}, 216 + {"OC_PLL_OFF", BIT(3)}, 217 + {"MAIN_PLL_OFF", BIT(4)}, 218 + {"XOSC_OFF", BIT(5)}, 219 + {"LPC_CLKS_GATED", BIT(6)}, 220 + {"PCIE_CLKREQS_IDLE", BIT(7)}, 221 + {"AUDIO_ROSC_OFF", BIT(8)}, 222 + {"HPET_XOSC_CLK_REQ", BIT(9)}, 223 + {"PMC_ROSC_SLOW_CLK", BIT(10)}, 224 + {"AON2_ROSC_GATED", BIT(11)}, 225 + {"CLKACKS_DEASSERTED", BIT(12)}, 226 + {} 227 + }; 228 + 229 + static const struct pmc_bit_map cnp_slps0_dbg2_map[] = { 230 + {"MPHY_CORE_GATED", BIT(0)}, 231 + {"CSME_GATED", BIT(1)}, 232 + {"USB2_SUS_GATED", BIT(2)}, 233 + {"DYN_FLEX_IO_IDLE", BIT(3)}, 234 + {"GBE_NO_LINK", BIT(4)}, 235 + {"THERM_SEN_DISABLED", BIT(5)}, 236 + {"PCIE_LOW_POWER", BIT(6)}, 237 + {"ISH_VNNAON_REQ_ACT", BIT(7)}, 238 + {"ISH_VNN_REQ_ACT", BIT(8)}, 239 + {"CNV_VNNAON_REQ_ACT", BIT(9)}, 240 + {"CNV_VNN_REQ_ACT", BIT(10)}, 241 + {"NPK_VNNON_REQ_ACT", BIT(11)}, 242 + {"PMSYNC_STATE_IDLE", BIT(12)}, 243 + {"ALST_GT_THRES", BIT(13)}, 244 + {"PMC_ARC_PG_READY", BIT(14)}, 245 + {} 246 + }; 247 + 248 + static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = { 249 + cnp_slps0_dbg0_map, 250 + cnp_slps0_dbg1_map, 251 + cnp_slps0_dbg2_map, 252 + NULL, 253 + }; 254 + 199 255 static const struct pmc_reg_map cnp_reg_map = { 200 256 .pfear_sts = cnp_pfear_map, 201 257 .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET, 258 + .slps0_dbg_maps = cnp_slps0_dbg_maps, 259 + .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET, 202 260 .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET, 203 261 .regmap_length = CNP_PMC_MMIO_REG_LEN, 204 262 .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A, ··· 310 252 } 311 253 312 254 #if IS_ENABLED(CONFIG_DEBUG_FS) 255 + static bool slps0_dbg_latch; 256 + 313 257 static void pmc_core_display_map(struct seq_file *s, int index, 314 258 u8 pf_reg, const struct pmc_bit_map *pf_map) 315 259 { ··· 541 481 .release = single_release, 542 482 }; 543 483 484 + static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset) 485 + { 486 + const struct pmc_reg_map *map = pmcdev->map; 487 + u32 fd; 488 + 489 + mutex_lock(&pmcdev->lock); 490 + 491 + if (!reset && !slps0_dbg_latch) 492 + goto out_unlock; 493 + 494 + fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset); 495 + if (reset) 496 + fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS; 497 + else 498 + fd |= CNP_PMC_LATCH_SLPS0_EVENTS; 499 + pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd); 500 + 501 + slps0_dbg_latch = 0; 502 + 503 + out_unlock: 504 + mutex_unlock(&pmcdev->lock); 505 + } 506 + 507 + static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused) 508 + { 509 + struct pmc_dev *pmcdev = s->private; 510 + const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps; 511 + const struct pmc_bit_map *map; 512 + int offset; 513 + u32 data; 514 + 515 + pmc_core_slps0_dbg_latch(pmcdev, false); 516 + offset = pmcdev->map->slps0_dbg_offset; 517 + while (*maps) { 518 + map = *maps; 519 + data = pmc_core_reg_read(pmcdev, offset); 520 + offset += 4; 521 + while (map->name) { 522 + seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n", 523 + map->name, 524 + data & map->bit_mask ? 525 + "Yes" : "No"); 526 + ++map; 527 + } 528 + ++maps; 529 + } 530 + pmc_core_slps0_dbg_latch(pmcdev, true); 531 + return 0; 532 + } 533 + DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg); 534 + 544 535 static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev) 545 536 { 546 537 debugfs_remove_recursive(pmcdev->dbgfs_dir); ··· 624 513 debugfs_create_file("mphy_core_lanes_power_gating_status", 625 514 0444, dir, pmcdev, 626 515 &pmc_core_mphy_pg_ops); 516 + 517 + if (pmcdev->map->slps0_dbg_maps) { 518 + debugfs_create_file("slp_s0_debug_status", 0444, 519 + dir, pmcdev, 520 + &pmc_core_slps0_dbg_fops); 521 + 522 + debugfs_create_bool("slp_s0_dbg_latch", 0644, 523 + dir, &slps0_dbg_latch); 524 + } 627 525 628 526 return 0; 629 527 }
+6
drivers/platform/x86/intel_pmc_core.h
··· 127 127 #define CNP_PMC_SLP_S0_RES_COUNTER_OFFSET 0x193C 128 128 #define CNP_PMC_LTR_IGNORE_OFFSET 0x1B0C 129 129 #define CNP_PMC_PM_CFG_OFFSET 0x1818 130 + #define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4 130 131 /* Cannonlake: PGD PFET Enable Ack Status Register(s) start */ 131 132 #define CNP_PMC_HOST_PPFEAR0A 0x1D90 132 133 133 134 #define CNP_PMC_MMIO_REG_LEN 0x2000 134 135 #define CNP_PPFEAR_NUM_ENTRIES 8 135 136 #define CNP_PMC_READ_DISABLE_BIT 22 137 + #define CNP_PMC_LATCH_SLPS0_EVENTS BIT(31) 136 138 137 139 struct pmc_bit_map { 138 140 const char *name; ··· 147 145 * @pfear_sts: Maps name of IP block to PPFEAR* bit 148 146 * @mphy_sts: Maps name of MPHY lane to MPHY status lane status bit 149 147 * @pll_sts: Maps name of PLL to corresponding bit status 148 + * @slps0_dbg_maps: Array of SLP_S0_DBG* registers containing debug info 150 149 * @slp_s0_offset: PWRMBASE offset to read SLP_S0 residency 151 150 * @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit 152 151 * @regmap_length: Length of memory to map from PWRMBASE address to access ··· 156 153 * PPFEAR 157 154 * @pm_cfg_offset: PWRMBASE offset to PM_CFG register 158 155 * @pm_read_disable_bit: Bit index to read PMC_READ_DISABLE 156 + * @slps0_dbg_offset: PWRMBASE offset to SLP_S0_DEBUG_REG* 159 157 * 160 158 * Each PCH has unique set of register offsets and bit indexes. This structure 161 159 * captures them to have a common implementation. ··· 165 161 const struct pmc_bit_map *pfear_sts; 166 162 const struct pmc_bit_map *mphy_sts; 167 163 const struct pmc_bit_map *pll_sts; 164 + const struct pmc_bit_map **slps0_dbg_maps; 168 165 const u32 slp_s0_offset; 169 166 const u32 ltr_ignore_offset; 170 167 const int regmap_length; ··· 173 168 const int ppfear_buckets; 174 169 const u32 pm_cfg_offset; 175 170 const int pm_read_disable_bit; 171 + const u32 slps0_dbg_offset; 176 172 }; 177 173 178 174 /**
+1
drivers/platform/x86/intel_punit_ipc.c
··· 18 18 #include <linux/bitops.h> 19 19 #include <linux/device.h> 20 20 #include <linux/interrupt.h> 21 + #include <linux/io.h> 21 22 #include <linux/platform_device.h> 22 23 #include <asm/intel_punit_ipc.h> 23 24
+481 -5
drivers/platform/x86/mlx-platform.c
··· 47 47 /* LPC bus IO offsets */ 48 48 #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 49 49 #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 50 + #define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00 51 + #define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 52 + #define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d 50 53 #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20 51 54 #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21 52 55 #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 53 56 #define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23 54 57 #define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24 58 + #define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30 59 + #define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET 0x31 60 + #define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET 0x32 61 + #define MLXPLAT_CPLD_LPC_REG_WP2_OFFSET 0x33 62 + #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 55 63 #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a 56 64 #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b 57 65 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 58 66 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 67 + #define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50 68 + #define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET 0x51 69 + #define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET 0x52 59 70 #define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58 60 71 #define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59 61 72 #define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a ··· 76 65 #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88 77 66 #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89 78 67 #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a 68 + #define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3 69 + #define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4 70 + #define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5 71 + #define MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET 0xe6 72 + #define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7 73 + #define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8 74 + #define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9 75 + #define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xea 76 + #define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xeb 77 + #define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xec 78 + #define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xed 79 + #define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xee 80 + #define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xef 79 81 #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 80 82 #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb 81 83 #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda 84 + 82 85 #define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL 83 86 #define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ 84 87 MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \ ··· 102 77 MLXPLAT_CPLD_LPC_PIO_OFFSET) 103 78 104 79 /* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */ 80 + #define MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF 0x04 105 81 #define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08 106 82 #define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08 107 83 #define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40 108 - #define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \ 84 + #define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF | \ 85 + MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \ 109 86 MLXPLAT_CPLD_AGGR_FAN_MASK_DEF) 87 + #define MLXPLAT_CPLD_AGGR_ASIC_MASK_NG 0x01 110 88 #define MLXPLAT_CPLD_AGGR_MASK_NG_DEF 0x04 111 - #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc0 112 - #define MLXPLAT_CPLD_AGGR_MASK_MSN21XX 0x04 89 + #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 113 90 #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) 114 91 #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) 115 92 #define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0) 93 + #define MLXPLAT_CPLD_ASIC_MASK GENMASK(1, 0) 116 94 #define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0) 117 95 #define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4) 118 96 #define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0) ··· 150 122 * @pdev_mux - array of mux platform devices 151 123 * @pdev_hotplug - hotplug platform devices 152 124 * @pdev_led - led platform devices 125 + * @pdev_io_regs - register access platform devices 126 + * @pdev_fan - FAN platform devices 153 127 */ 154 128 struct mlxplat_priv { 155 129 struct platform_device *pdev_i2c; 156 130 struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS]; 157 131 struct platform_device *pdev_hotplug; 158 132 struct platform_device *pdev_led; 133 + struct platform_device *pdev_io_regs; 134 + struct platform_device *pdev_fan; 159 135 }; 160 136 161 137 /* Regions for LPC I2C controller and LPC base register space */ ··· 320 288 }, 321 289 }; 322 290 291 + static struct mlxreg_core_data mlxplat_mlxcpld_default_asic_items_data[] = { 292 + { 293 + .label = "asic1", 294 + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 295 + .mask = MLXPLAT_CPLD_ASIC_MASK, 296 + .hpdev.nr = MLXPLAT_CPLD_NR_NONE, 297 + }, 298 + }; 299 + 323 300 static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { 324 301 { 325 302 .data = mlxplat_mlxcpld_default_psu_items_data, ··· 357 316 .inversed = 1, 358 317 .health = false, 359 318 }, 319 + { 320 + .data = mlxplat_mlxcpld_default_asic_items_data, 321 + .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, 322 + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 323 + .mask = MLXPLAT_CPLD_ASIC_MASK, 324 + .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 325 + .inversed = 0, 326 + .health = true, 327 + }, 360 328 }; 361 329 362 330 static ··· 374 324 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items), 375 325 .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, 376 326 .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, 327 + .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, 328 + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, 377 329 }; 378 330 379 331 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = { ··· 403 351 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_pwr_items_data), 404 352 .inversed = 0, 405 353 .health = false, 354 + }, 355 + { 356 + .data = mlxplat_mlxcpld_default_asic_items_data, 357 + .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, 358 + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 359 + .mask = MLXPLAT_CPLD_ASIC_MASK, 360 + .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 361 + .inversed = 0, 362 + .health = true, 406 363 }, 407 364 }; 408 365 ··· 515 454 .inversed = 1, 516 455 .health = false, 517 456 }, 457 + { 458 + .data = mlxplat_mlxcpld_default_asic_items_data, 459 + .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 460 + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 461 + .mask = MLXPLAT_CPLD_ASIC_MASK, 462 + .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 463 + .inversed = 0, 464 + .health = true, 465 + }, 518 466 }; 519 467 520 468 static ··· 561 491 .count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data), 562 492 .inversed = 0, 563 493 .health = false, 494 + }, 495 + { 496 + .data = mlxplat_mlxcpld_default_asic_items_data, 497 + .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, 498 + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 499 + .mask = MLXPLAT_CPLD_ASIC_MASK, 500 + .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 501 + .inversed = 0, 502 + .health = true, 564 503 }, 565 504 }; 566 505 ··· 667 588 .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), 668 589 .inversed = 1, 669 590 .health = false, 591 + }, 592 + { 593 + .data = mlxplat_mlxcpld_default_asic_items_data, 594 + .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, 595 + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 596 + .mask = MLXPLAT_CPLD_ASIC_MASK, 597 + .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), 598 + .inversed = 0, 599 + .health = true, 670 600 }, 671 601 }; 672 602 ··· 901 813 .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data), 902 814 }; 903 815 816 + /* Platform register access default */ 817 + static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { 818 + { 819 + .label = "cpld1_version", 820 + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, 821 + .bit = GENMASK(7, 0), 822 + .mode = 0444, 823 + }, 824 + { 825 + .label = "cpld2_version", 826 + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, 827 + .bit = GENMASK(7, 0), 828 + .mode = 0444, 829 + }, 830 + { 831 + .label = "reset_long_pb", 832 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 833 + .mask = GENMASK(7, 0) & ~BIT(0), 834 + .mode = 0444, 835 + }, 836 + { 837 + .label = "reset_short_pb", 838 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 839 + .mask = GENMASK(7, 0) & ~BIT(1), 840 + .mode = 0444, 841 + }, 842 + { 843 + .label = "reset_aux_pwr_or_ref", 844 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 845 + .mask = GENMASK(7, 0) & ~BIT(2), 846 + .mode = 0444, 847 + }, 848 + { 849 + .label = "reset_main_pwr_fail", 850 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 851 + .mask = GENMASK(7, 0) & ~BIT(3), 852 + .mode = 0444, 853 + }, 854 + { 855 + .label = "reset_sw_reset", 856 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 857 + .mask = GENMASK(7, 0) & ~BIT(4), 858 + .mode = 0444, 859 + }, 860 + { 861 + .label = "reset_fw_reset", 862 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 863 + .mask = GENMASK(7, 0) & ~BIT(5), 864 + .mode = 0444, 865 + }, 866 + { 867 + .label = "reset_hotswap_or_wd", 868 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 869 + .mask = GENMASK(7, 0) & ~BIT(6), 870 + .mode = 0444, 871 + }, 872 + { 873 + .label = "reset_asic_thermal", 874 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 875 + .mask = GENMASK(7, 0) & ~BIT(7), 876 + .mode = 0444, 877 + }, 878 + { 879 + .label = "psu1_on", 880 + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 881 + .mask = GENMASK(7, 0) & ~BIT(0), 882 + .mode = 0200, 883 + }, 884 + { 885 + .label = "psu2_on", 886 + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 887 + .mask = GENMASK(7, 0) & ~BIT(1), 888 + .mode = 0200, 889 + }, 890 + { 891 + .label = "pwr_cycle", 892 + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 893 + .mask = GENMASK(7, 0) & ~BIT(2), 894 + .mode = 0200, 895 + }, 896 + { 897 + .label = "pwr_down", 898 + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 899 + .mask = GENMASK(7, 0) & ~BIT(3), 900 + .mode = 0200, 901 + }, 902 + { 903 + .label = "select_iio", 904 + .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, 905 + .mask = GENMASK(7, 0) & ~BIT(6), 906 + .mode = 0644, 907 + }, 908 + { 909 + .label = "asic_health", 910 + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 911 + .mask = MLXPLAT_CPLD_ASIC_MASK, 912 + .bit = 1, 913 + .mode = 0444, 914 + }, 915 + }; 916 + 917 + static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = { 918 + .data = mlxplat_mlxcpld_default_regs_io_data, 919 + .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data), 920 + }; 921 + 922 + /* Platform register access MSN21xx, MSN201x, MSN274x systems families data */ 923 + static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = { 924 + { 925 + .label = "cpld1_version", 926 + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, 927 + .bit = GENMASK(7, 0), 928 + .mode = 0444, 929 + }, 930 + { 931 + .label = "cpld2_version", 932 + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, 933 + .bit = GENMASK(7, 0), 934 + .mode = 0444, 935 + }, 936 + { 937 + .label = "reset_long_pb", 938 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 939 + .mask = GENMASK(7, 0) & ~BIT(0), 940 + .mode = 0444, 941 + }, 942 + { 943 + .label = "reset_short_pb", 944 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 945 + .mask = GENMASK(7, 0) & ~BIT(1), 946 + .mode = 0444, 947 + }, 948 + { 949 + .label = "reset_aux_pwr_or_ref", 950 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 951 + .mask = GENMASK(7, 0) & ~BIT(2), 952 + .mode = 0444, 953 + }, 954 + { 955 + .label = "reset_sw_reset", 956 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 957 + .mask = GENMASK(7, 0) & ~BIT(3), 958 + .mode = 0444, 959 + }, 960 + { 961 + .label = "reset_main_pwr_fail", 962 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 963 + .mask = GENMASK(7, 0) & ~BIT(4), 964 + .mode = 0444, 965 + }, 966 + { 967 + .label = "reset_asic_thermal", 968 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 969 + .mask = GENMASK(7, 0) & ~BIT(5), 970 + .mode = 0444, 971 + }, 972 + { 973 + .label = "reset_hotswap_or_halt", 974 + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, 975 + .mask = GENMASK(7, 0) & ~BIT(6), 976 + .mode = 0444, 977 + }, 978 + { 979 + .label = "psu1_on", 980 + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 981 + .mask = GENMASK(7, 0) & ~BIT(0), 982 + .mode = 0200, 983 + }, 984 + { 985 + .label = "psu2_on", 986 + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 987 + .mask = GENMASK(7, 0) & ~BIT(1), 988 + .mode = 0200, 989 + }, 990 + { 991 + .label = "pwr_cycle", 992 + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 993 + .mask = GENMASK(7, 0) & ~BIT(2), 994 + .mode = 0200, 995 + }, 996 + { 997 + .label = "pwr_down", 998 + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, 999 + .mask = GENMASK(7, 0) & ~BIT(3), 1000 + .mode = 0200, 1001 + }, 1002 + { 1003 + .label = "asic_health", 1004 + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, 1005 + .mask = MLXPLAT_CPLD_ASIC_MASK, 1006 + .bit = 1, 1007 + .mode = 0444, 1008 + }, 1009 + }; 1010 + 1011 + static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = { 1012 + .data = mlxplat_mlxcpld_msn21xx_regs_io_data, 1013 + .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data), 1014 + }; 1015 + 1016 + /* Platform FAN default */ 1017 + static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { 1018 + { 1019 + .label = "pwm1", 1020 + .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET, 1021 + }, 1022 + { 1023 + .label = "tacho1", 1024 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET, 1025 + .mask = GENMASK(7, 0), 1026 + }, 1027 + { 1028 + .label = "tacho2", 1029 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET, 1030 + .mask = GENMASK(7, 0), 1031 + }, 1032 + { 1033 + .label = "tacho3", 1034 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET, 1035 + .mask = GENMASK(7, 0), 1036 + }, 1037 + { 1038 + .label = "tacho4", 1039 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET, 1040 + .mask = GENMASK(7, 0), 1041 + }, 1042 + { 1043 + .label = "tacho5", 1044 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET, 1045 + .mask = GENMASK(7, 0), 1046 + }, 1047 + { 1048 + .label = "tacho6", 1049 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET, 1050 + .mask = GENMASK(7, 0), 1051 + }, 1052 + { 1053 + .label = "tacho7", 1054 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET, 1055 + .mask = GENMASK(7, 0), 1056 + }, 1057 + { 1058 + .label = "tacho8", 1059 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET, 1060 + .mask = GENMASK(7, 0), 1061 + }, 1062 + { 1063 + .label = "tacho9", 1064 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET, 1065 + .mask = GENMASK(7, 0), 1066 + }, 1067 + { 1068 + .label = "tacho10", 1069 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET, 1070 + .mask = GENMASK(7, 0), 1071 + }, 1072 + { 1073 + .label = "tacho11", 1074 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET, 1075 + .mask = GENMASK(7, 0), 1076 + }, 1077 + { 1078 + .label = "tacho12", 1079 + .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET, 1080 + .mask = GENMASK(7, 0), 1081 + }, 1082 + }; 1083 + 1084 + static struct mlxreg_core_platform_data mlxplat_default_fan_data = { 1085 + .data = mlxplat_mlxcpld_default_fan_data, 1086 + .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data), 1087 + }; 904 1088 905 1089 static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) 906 1090 { ··· 1182 822 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: 1183 823 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: 1184 824 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: 825 + case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: 826 + case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: 827 + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: 828 + case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: 1185 829 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: 1186 830 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: 831 + case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: 832 + case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: 1187 833 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: 1188 834 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: 1189 835 case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: 1190 836 case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: 1191 837 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: 1192 838 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: 839 + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: 840 + case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: 1193 841 return true; 1194 842 } 1195 843 return false; ··· 1206 838 static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) 1207 839 { 1208 840 switch (reg) { 841 + case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: 842 + case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: 843 + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: 1209 844 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: 1210 845 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: 1211 846 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: 1212 847 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: 1213 848 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: 849 + case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: 850 + case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: 851 + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: 852 + case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: 1214 853 case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: 1215 854 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: 1216 855 case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: 1217 856 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: 857 + case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: 858 + case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: 859 + case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: 1218 860 case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: 1219 861 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: 1220 862 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: ··· 1234 856 case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: 1235 857 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: 1236 858 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: 859 + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: 860 + case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: 861 + case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: 862 + case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET: 863 + case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET: 864 + case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET: 865 + case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET: 866 + case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET: 867 + case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET: 868 + case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET: 869 + case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET: 870 + case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET: 871 + case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET: 872 + case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: 1237 873 return true; 1238 874 } 1239 875 return false; ··· 1256 864 static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) 1257 865 { 1258 866 switch (reg) { 867 + case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: 868 + case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: 869 + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: 1259 870 case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: 1260 871 case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: 1261 872 case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: 1262 873 case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: 1263 874 case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: 875 + case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: 876 + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: 1264 877 case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: 1265 878 case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: 1266 879 case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: 1267 880 case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: 881 + case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: 882 + case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: 883 + case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: 1268 884 case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: 1269 885 case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: 1270 886 case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: ··· 1282 882 case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: 1283 883 case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: 1284 884 case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: 885 + case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: 886 + case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: 887 + case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: 888 + case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET: 889 + case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET: 890 + case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET: 891 + case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET: 892 + case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET: 893 + case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET: 894 + case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET: 895 + case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET: 896 + case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET: 897 + case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET: 898 + case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: 1285 899 return true; 1286 900 } 1287 901 return false; 1288 902 } 903 + 904 + static const struct reg_default mlxplat_mlxcpld_regmap_default[] = { 905 + { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 }, 906 + { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 }, 907 + { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, 908 + }; 1289 909 1290 910 struct mlxplat_mlxcpld_regmap_context { 1291 911 void __iomem *base; ··· 1339 919 .writeable_reg = mlxplat_mlxcpld_writeable_reg, 1340 920 .readable_reg = mlxplat_mlxcpld_readable_reg, 1341 921 .volatile_reg = mlxplat_mlxcpld_volatile_reg, 922 + .reg_defaults = mlxplat_mlxcpld_regmap_default, 923 + .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default), 1342 924 .reg_read = mlxplat_mlxcpld_reg_read, 1343 925 .reg_write = mlxplat_mlxcpld_reg_write, 1344 926 }; ··· 1352 930 static struct platform_device *mlxplat_dev; 1353 931 static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug; 1354 932 static struct mlxreg_core_platform_data *mlxplat_led; 933 + static struct mlxreg_core_platform_data *mlxplat_regs_io; 934 + static struct mlxreg_core_platform_data *mlxplat_fan; 1355 935 1356 936 static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) 1357 937 { ··· 1368 944 mlxplat_hotplug->deferred_nr = 1369 945 mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1370 946 mlxplat_led = &mlxplat_default_led_data; 947 + mlxplat_regs_io = &mlxplat_default_regs_io_data; 1371 948 1372 949 return 1; 1373 950 }; ··· 1386 961 mlxplat_hotplug->deferred_nr = 1387 962 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1388 963 mlxplat_led = &mlxplat_msn21xx_led_data; 964 + mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; 1389 965 1390 966 return 1; 1391 967 }; ··· 1404 978 mlxplat_hotplug->deferred_nr = 1405 979 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1406 980 mlxplat_led = &mlxplat_default_led_data; 981 + mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; 1407 982 1408 983 return 1; 1409 984 }; ··· 1422 995 mlxplat_hotplug->deferred_nr = 1423 996 mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1424 997 mlxplat_led = &mlxplat_default_ng_led_data; 998 + mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; 1425 999 1426 1000 return 1; 1427 1001 }; ··· 1440 1012 mlxplat_hotplug->deferred_nr = 1441 1013 mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; 1442 1014 mlxplat_led = &mlxplat_msn21xx_led_data; 1015 + mlxplat_fan = &mlxplat_default_fan_data; 1443 1016 1444 1017 return 1; 1445 1018 }; ··· 1592 1163 static int __init mlxplat_init(void) 1593 1164 { 1594 1165 struct mlxplat_priv *priv; 1595 - int i, nr, err; 1166 + int i, j, nr, err; 1596 1167 1597 1168 if (!dmi_check_system(mlxplat_dmi_table)) 1598 1169 return -ENODEV; ··· 1662 1233 goto fail_platform_mux_register; 1663 1234 } 1664 1235 1236 + /* Set default registers. */ 1237 + for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) { 1238 + err = regmap_write(mlxplat_hotplug->regmap, 1239 + mlxplat_mlxcpld_regmap_default[j].reg, 1240 + mlxplat_mlxcpld_regmap_default[j].def); 1241 + if (err) 1242 + goto fail_platform_mux_register; 1243 + } 1244 + 1665 1245 /* Add LED driver. */ 1666 1246 mlxplat_led->regmap = mlxplat_hotplug->regmap; 1667 1247 priv->pdev_led = platform_device_register_resndata( ··· 1682 1244 goto fail_platform_hotplug_register; 1683 1245 } 1684 1246 1247 + /* Add registers io access driver. */ 1248 + if (mlxplat_regs_io) { 1249 + mlxplat_regs_io->regmap = mlxplat_hotplug->regmap; 1250 + priv->pdev_io_regs = platform_device_register_resndata( 1251 + &mlxplat_dev->dev, "mlxreg-io", 1252 + PLATFORM_DEVID_NONE, NULL, 0, 1253 + mlxplat_regs_io, 1254 + sizeof(*mlxplat_regs_io)); 1255 + if (IS_ERR(priv->pdev_io_regs)) { 1256 + err = PTR_ERR(priv->pdev_io_regs); 1257 + goto fail_platform_led_register; 1258 + } 1259 + } 1260 + 1261 + /* Add FAN driver. */ 1262 + if (mlxplat_fan) { 1263 + mlxplat_fan->regmap = mlxplat_hotplug->regmap; 1264 + priv->pdev_fan = platform_device_register_resndata( 1265 + &mlxplat_dev->dev, "mlxreg-fan", 1266 + PLATFORM_DEVID_NONE, NULL, 0, 1267 + mlxplat_fan, 1268 + sizeof(*mlxplat_fan)); 1269 + if (IS_ERR(priv->pdev_fan)) { 1270 + err = PTR_ERR(priv->pdev_fan); 1271 + goto fail_platform_io_regs_register; 1272 + } 1273 + } 1274 + 1685 1275 /* Sync registers with hardware. */ 1686 1276 regcache_mark_dirty(mlxplat_hotplug->regmap); 1687 1277 err = regcache_sync(mlxplat_hotplug->regmap); 1688 1278 if (err) 1689 - goto fail_platform_led_register; 1279 + goto fail_platform_fan_register; 1690 1280 1691 1281 return 0; 1692 1282 1283 + fail_platform_fan_register: 1284 + if (mlxplat_fan) 1285 + platform_device_unregister(priv->pdev_fan); 1286 + fail_platform_io_regs_register: 1287 + if (mlxplat_regs_io) 1288 + platform_device_unregister(priv->pdev_io_regs); 1693 1289 fail_platform_led_register: 1694 1290 platform_device_unregister(priv->pdev_led); 1695 1291 fail_platform_hotplug_register: ··· 1744 1272 struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); 1745 1273 int i; 1746 1274 1275 + if (priv->pdev_fan) 1276 + platform_device_unregister(priv->pdev_fan); 1277 + if (priv->pdev_io_regs) 1278 + platform_device_unregister(priv->pdev_io_regs); 1747 1279 platform_device_unregister(priv->pdev_led); 1748 1280 platform_device_unregister(priv->pdev_hotplug); 1749 1281
-623
drivers/platform/x86/silead_dmi.c
··· 1 - /* 2 - * Silead touchscreen driver DMI based configuration code 3 - * 4 - * Copyright (c) 2017 Red Hat Inc. 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; either version 2 of the License, or 9 - * (at your option) any later version. 10 - * 11 - * Red Hat authors: 12 - * Hans de Goede <hdegoede@redhat.com> 13 - */ 14 - 15 - #include <linux/acpi.h> 16 - #include <linux/device.h> 17 - #include <linux/dmi.h> 18 - #include <linux/i2c.h> 19 - #include <linux/notifier.h> 20 - #include <linux/property.h> 21 - #include <linux/string.h> 22 - 23 - struct silead_ts_dmi_data { 24 - const char *acpi_name; 25 - const struct property_entry *properties; 26 - }; 27 - 28 - static const struct property_entry cube_iwork8_air_props[] = { 29 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1660), 30 - PROPERTY_ENTRY_U32("touchscreen-size-y", 900), 31 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 32 - PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"), 33 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 34 - { } 35 - }; 36 - 37 - static const struct silead_ts_dmi_data cube_iwork8_air_data = { 38 - .acpi_name = "MSSL1680:00", 39 - .properties = cube_iwork8_air_props, 40 - }; 41 - 42 - static const struct property_entry jumper_ezpad_mini3_props[] = { 43 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1700), 44 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1150), 45 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 46 - PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"), 47 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 48 - { } 49 - }; 50 - 51 - static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = { 52 - .acpi_name = "MSSL1680:00", 53 - .properties = jumper_ezpad_mini3_props, 54 - }; 55 - 56 - static const struct property_entry jumper_ezpad_6_pro_props[] = { 57 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), 58 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1500), 59 - PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"), 60 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 61 - PROPERTY_ENTRY_BOOL("silead,home-button"), 62 - { } 63 - }; 64 - 65 - static const struct silead_ts_dmi_data jumper_ezpad_6_pro_data = { 66 - .acpi_name = "MSSL1680:00", 67 - .properties = jumper_ezpad_6_pro_props, 68 - }; 69 - 70 - static const struct property_entry dexp_ursus_7w_props[] = { 71 - PROPERTY_ENTRY_U32("touchscreen-size-x", 890), 72 - PROPERTY_ENTRY_U32("touchscreen-size-y", 630), 73 - PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"), 74 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 75 - PROPERTY_ENTRY_BOOL("silead,home-button"), 76 - { } 77 - }; 78 - 79 - static const struct silead_ts_dmi_data dexp_ursus_7w_data = { 80 - .acpi_name = "MSSL1680:00", 81 - .properties = dexp_ursus_7w_props, 82 - }; 83 - 84 - static const struct property_entry surftab_twin_10_1_st10432_8_props[] = { 85 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1900), 86 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1280), 87 - PROPERTY_ENTRY_U32("touchscreen-inverted-y", 1), 88 - PROPERTY_ENTRY_STRING("firmware-name", 89 - "gsl3670-surftab-twin-10-1-st10432-8.fw"), 90 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 91 - { } 92 - }; 93 - 94 - static const struct silead_ts_dmi_data surftab_twin_10_1_st10432_8_data = { 95 - .acpi_name = "MSSL1680:00", 96 - .properties = surftab_twin_10_1_st10432_8_props, 97 - }; 98 - 99 - static const struct property_entry surftab_wintron70_st70416_6_props[] = { 100 - PROPERTY_ENTRY_U32("touchscreen-size-x", 884), 101 - PROPERTY_ENTRY_U32("touchscreen-size-y", 632), 102 - PROPERTY_ENTRY_STRING("firmware-name", 103 - "gsl1686-surftab-wintron70-st70416-6.fw"), 104 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 105 - PROPERTY_ENTRY_BOOL("silead,home-button"), 106 - { } 107 - }; 108 - 109 - static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = { 110 - .acpi_name = "MSSL1680:00", 111 - .properties = surftab_wintron70_st70416_6_props, 112 - }; 113 - 114 - static const struct property_entry gp_electronic_t701_props[] = { 115 - PROPERTY_ENTRY_U32("touchscreen-size-x", 960), 116 - PROPERTY_ENTRY_U32("touchscreen-size-y", 640), 117 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 118 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 119 - PROPERTY_ENTRY_STRING("firmware-name", 120 - "gsl1680-gp-electronic-t701.fw"), 121 - { } 122 - }; 123 - 124 - static const struct silead_ts_dmi_data gp_electronic_t701_data = { 125 - .acpi_name = "MSSL1680:00", 126 - .properties = gp_electronic_t701_props, 127 - }; 128 - 129 - static const struct property_entry pipo_w2s_props[] = { 130 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1660), 131 - PROPERTY_ENTRY_U32("touchscreen-size-y", 880), 132 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 133 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 134 - PROPERTY_ENTRY_STRING("firmware-name", 135 - "gsl1680-pipo-w2s.fw"), 136 - { } 137 - }; 138 - 139 - static const struct silead_ts_dmi_data pipo_w2s_data = { 140 - .acpi_name = "MSSL1680:00", 141 - .properties = pipo_w2s_props, 142 - }; 143 - 144 - static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = { 145 - PROPERTY_ENTRY_U32("touchscreen-min-x", 32), 146 - PROPERTY_ENTRY_U32("touchscreen-min-y", 16), 147 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1692), 148 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1146), 149 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 150 - PROPERTY_ENTRY_STRING("firmware-name", 151 - "gsl3680-pov-mobii-wintab-p800w-v20.fw"), 152 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 153 - PROPERTY_ENTRY_BOOL("silead,home-button"), 154 - { } 155 - }; 156 - 157 - static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v20_data = { 158 - .acpi_name = "MSSL1680:00", 159 - .properties = pov_mobii_wintab_p800w_v20_props, 160 - }; 161 - 162 - static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = { 163 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1800), 164 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1150), 165 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 166 - PROPERTY_ENTRY_STRING("firmware-name", 167 - "gsl3692-pov-mobii-wintab-p800w.fw"), 168 - PROPERTY_ENTRY_BOOL("silead,home-button"), 169 - { } 170 - }; 171 - 172 - static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v21_data = { 173 - .acpi_name = "MSSL1680:00", 174 - .properties = pov_mobii_wintab_p800w_v21_props, 175 - }; 176 - 177 - static const struct property_entry itworks_tw891_props[] = { 178 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1600), 179 - PROPERTY_ENTRY_U32("touchscreen-size-y", 890), 180 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 181 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 182 - PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"), 183 - { } 184 - }; 185 - 186 - static const struct silead_ts_dmi_data itworks_tw891_data = { 187 - .acpi_name = "MSSL1680:00", 188 - .properties = itworks_tw891_props, 189 - }; 190 - 191 - static const struct property_entry chuwi_hi8_pro_props[] = { 192 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1728), 193 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1148), 194 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 195 - PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"), 196 - PROPERTY_ENTRY_BOOL("silead,home-button"), 197 - { } 198 - }; 199 - 200 - static const struct silead_ts_dmi_data chuwi_hi8_pro_data = { 201 - .acpi_name = "MSSL1680:00", 202 - .properties = chuwi_hi8_pro_props, 203 - }; 204 - 205 - static const struct property_entry digma_citi_e200_props[] = { 206 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), 207 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1500), 208 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 209 - PROPERTY_ENTRY_STRING("firmware-name", 210 - "gsl1686-digma_citi_e200.fw"), 211 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 212 - PROPERTY_ENTRY_BOOL("silead,home-button"), 213 - { } 214 - }; 215 - 216 - static const struct silead_ts_dmi_data digma_citi_e200_data = { 217 - .acpi_name = "MSSL1680:00", 218 - .properties = digma_citi_e200_props, 219 - }; 220 - 221 - static const struct property_entry onda_obook_20_plus_props[] = { 222 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1728), 223 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1148), 224 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 225 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 226 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 227 - PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-obook-20-plus.fw"), 228 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 229 - PROPERTY_ENTRY_BOOL("silead,home-button"), 230 - { } 231 - }; 232 - 233 - static const struct silead_ts_dmi_data onda_obook_20_plus_data = { 234 - .acpi_name = "MSSL1680:00", 235 - .properties = onda_obook_20_plus_props, 236 - }; 237 - 238 - static const struct property_entry chuwi_hi8_props[] = { 239 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1665), 240 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), 241 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 242 - PROPERTY_ENTRY_BOOL("silead,home-button"), 243 - PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"), 244 - { } 245 - }; 246 - 247 - static const struct silead_ts_dmi_data chuwi_hi8_data = { 248 - .acpi_name = "MSSL0001:00", 249 - .properties = chuwi_hi8_props, 250 - }; 251 - 252 - static const struct property_entry chuwi_vi8_props[] = { 253 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1724), 254 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), 255 - PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 256 - PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-vi8.fw"), 257 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 258 - PROPERTY_ENTRY_BOOL("silead,home-button"), 259 - { } 260 - }; 261 - 262 - static const struct silead_ts_dmi_data chuwi_vi8_data = { 263 - .acpi_name = "MSSL1680:00", 264 - .properties = chuwi_vi8_props, 265 - }; 266 - 267 - static const struct property_entry trekstor_primebook_c13_props[] = { 268 - PROPERTY_ENTRY_U32("touchscreen-size-x", 2624), 269 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1920), 270 - PROPERTY_ENTRY_STRING("firmware-name", 271 - "gsl1680-trekstor-primebook-c13.fw"), 272 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 273 - PROPERTY_ENTRY_BOOL("silead,home-button"), 274 - { } 275 - }; 276 - 277 - static const struct silead_ts_dmi_data trekstor_primebook_c13_data = { 278 - .acpi_name = "MSSL1680:00", 279 - .properties = trekstor_primebook_c13_props, 280 - }; 281 - 282 - static const struct property_entry teclast_x98plus2_props[] = { 283 - PROPERTY_ENTRY_U32("touchscreen-size-x", 2048), 284 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1280), 285 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 286 - PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 287 - PROPERTY_ENTRY_STRING("firmware-name", 288 - "gsl1686-teclast_x98plus2.fw"), 289 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 290 - { } 291 - }; 292 - 293 - static const struct silead_ts_dmi_data teclast_x98plus2_data = { 294 - .acpi_name = "MSSL1680:00", 295 - .properties = teclast_x98plus2_props, 296 - }; 297 - 298 - static const struct property_entry teclast_x3_plus_props[] = { 299 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), 300 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1500), 301 - PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-teclast-x3-plus.fw"), 302 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 303 - PROPERTY_ENTRY_BOOL("silead,home-button"), 304 - { } 305 - }; 306 - 307 - static const struct silead_ts_dmi_data teclast_x3_plus_data = { 308 - .acpi_name = "MSSL1680:00", 309 - .properties = teclast_x3_plus_props, 310 - }; 311 - 312 - static const struct property_entry onda_v891w_v1_props[] = { 313 - PROPERTY_ENTRY_U32("touchscreen-min-x", 46), 314 - PROPERTY_ENTRY_U32("touchscreen-min-y", 8), 315 - PROPERTY_ENTRY_U32("touchscreen-size-x", 1676), 316 - PROPERTY_ENTRY_U32("touchscreen-size-y", 1130), 317 - PROPERTY_ENTRY_STRING("firmware-name", 318 - "gsl3680-onda-v891w-v1.fw"), 319 - PROPERTY_ENTRY_U32("silead,max-fingers", 10), 320 - PROPERTY_ENTRY_BOOL("silead,home-button"), 321 - { } 322 - }; 323 - 324 - static const struct silead_ts_dmi_data onda_v891w_v1_data = { 325 - .acpi_name = "MSSL1680:00", 326 - .properties = onda_v891w_v1_props, 327 - }; 328 - 329 - static const struct dmi_system_id silead_ts_dmi_table[] = { 330 - { 331 - /* CUBE iwork8 Air */ 332 - .driver_data = (void *)&cube_iwork8_air_data, 333 - .matches = { 334 - DMI_MATCH(DMI_SYS_VENDOR, "cube"), 335 - DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"), 336 - DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), 337 - }, 338 - }, 339 - { 340 - /* Jumper EZpad mini3 */ 341 - .driver_data = (void *)&jumper_ezpad_mini3_data, 342 - .matches = { 343 - DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 344 - /* jumperx.T87.KFBNEEA02 with the version-nr dropped */ 345 - DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"), 346 - }, 347 - }, 348 - { 349 - /* Jumper EZpad 6 Pro */ 350 - .driver_data = (void *)&jumper_ezpad_6_pro_data, 351 - .matches = { 352 - DMI_MATCH(DMI_SYS_VENDOR, "Jumper"), 353 - DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"), 354 - DMI_MATCH(DMI_BIOS_VERSION, "5.12"), 355 - /* Above matches are too generic, add bios-date match */ 356 - DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"), 357 - }, 358 - }, 359 - { 360 - /* DEXP Ursus 7W */ 361 - .driver_data = (void *)&dexp_ursus_7w_data, 362 - .matches = { 363 - DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 364 - DMI_MATCH(DMI_PRODUCT_NAME, "7W"), 365 - }, 366 - }, 367 - { 368 - /* TrekStor SurfTab twin 10.1 ST10432-8 */ 369 - .driver_data = (void *)&surftab_twin_10_1_st10432_8_data, 370 - .matches = { 371 - DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"), 372 - DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab twin 10.1"), 373 - }, 374 - }, 375 - { 376 - /* Trekstor Surftab Wintron 7.0 ST70416-6 */ 377 - .driver_data = (void *)&surftab_wintron70_st70416_6_data, 378 - .matches = { 379 - DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 380 - DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"), 381 - /* Exact match, different versions need different fw */ 382 - DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"), 383 - }, 384 - }, 385 - { 386 - /* Trekstor Surftab Wintron 7.0 ST70416-6, newer BIOS */ 387 - .driver_data = (void *)&surftab_wintron70_st70416_6_data, 388 - .matches = { 389 - DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"), 390 - DMI_MATCH(DMI_PRODUCT_NAME, 391 - "SurfTab wintron 7.0 ST70416-6"), 392 - /* Exact match, different versions need different fw */ 393 - DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA05"), 394 - }, 395 - }, 396 - { 397 - /* Ployer Momo7w (same hardware as the Trekstor ST70416-6) */ 398 - .driver_data = (void *)&surftab_wintron70_st70416_6_data, 399 - .matches = { 400 - DMI_MATCH(DMI_SYS_VENDOR, "Shenzhen PLOYER"), 401 - DMI_MATCH(DMI_PRODUCT_NAME, "MOMO7W"), 402 - /* Exact match, different versions need different fw */ 403 - DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"), 404 - }, 405 - }, 406 - { 407 - /* GP-electronic T701 */ 408 - .driver_data = (void *)&gp_electronic_t701_data, 409 - .matches = { 410 - DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 411 - DMI_MATCH(DMI_PRODUCT_NAME, "T701"), 412 - DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"), 413 - }, 414 - }, 415 - { 416 - /* Pipo W2S */ 417 - .driver_data = (void *)&pipo_w2s_data, 418 - .matches = { 419 - DMI_MATCH(DMI_SYS_VENDOR, "PIPO"), 420 - DMI_MATCH(DMI_PRODUCT_NAME, "W2S"), 421 - }, 422 - }, 423 - { 424 - /* Point of View mobii wintab p800w (v2.0) */ 425 - .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data, 426 - .matches = { 427 - DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 428 - DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 429 - DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"), 430 - /* Above matches are too generic, add bios-date match */ 431 - DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"), 432 - }, 433 - }, 434 - { 435 - /* Point of View mobii wintab p800w (v2.1) */ 436 - .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data, 437 - .matches = { 438 - DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 439 - DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 440 - DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"), 441 - /* Above matches are too generic, add bios-date match */ 442 - DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), 443 - }, 444 - }, 445 - { 446 - /* I.T.Works TW891 */ 447 - .driver_data = (void *)&itworks_tw891_data, 448 - .matches = { 449 - DMI_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), 450 - DMI_MATCH(DMI_PRODUCT_NAME, "TW891"), 451 - }, 452 - }, 453 - { 454 - /* Chuwi Hi8 Pro */ 455 - .driver_data = (void *)&chuwi_hi8_pro_data, 456 - .matches = { 457 - DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"), 458 - DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"), 459 - }, 460 - }, 461 - { 462 - /* Digma Citi E200 */ 463 - .driver_data = (void *)&digma_citi_e200_data, 464 - .matches = { 465 - DMI_MATCH(DMI_SYS_VENDOR, "Digma"), 466 - DMI_MATCH(DMI_PRODUCT_NAME, "CITI E200"), 467 - DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), 468 - }, 469 - }, 470 - { 471 - /* Onda oBook 20 Plus */ 472 - .driver_data = (void *)&onda_obook_20_plus_data, 473 - .matches = { 474 - DMI_MATCH(DMI_SYS_VENDOR, "ONDA"), 475 - DMI_MATCH(DMI_PRODUCT_NAME, "OBOOK 20 PLUS"), 476 - }, 477 - }, 478 - { 479 - /* Chuwi Hi8 */ 480 - .driver_data = (void *)&chuwi_hi8_data, 481 - .matches = { 482 - DMI_MATCH(DMI_SYS_VENDOR, "ilife"), 483 - DMI_MATCH(DMI_PRODUCT_NAME, "S806"), 484 - }, 485 - }, 486 - { 487 - /* Chuwi Hi8 (H1D_S806_206) */ 488 - .driver_data = (void *)&chuwi_hi8_data, 489 - .matches = { 490 - DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 491 - DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"), 492 - DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"), 493 - }, 494 - }, 495 - { 496 - /* Chuwi Vi8 (CWI506) */ 497 - .driver_data = (void *)&chuwi_vi8_data, 498 - .matches = { 499 - DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 500 - DMI_MATCH(DMI_PRODUCT_NAME, "i86"), 501 - DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"), 502 - }, 503 - }, 504 - { 505 - /* Trekstor Primebook C13 */ 506 - .driver_data = (void *)&trekstor_primebook_c13_data, 507 - .matches = { 508 - DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"), 509 - DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"), 510 - }, 511 - }, 512 - { 513 - /* Teclast X98 Plus II */ 514 - .driver_data = (void *)&teclast_x98plus2_data, 515 - .matches = { 516 - DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), 517 - DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"), 518 - }, 519 - }, 520 - { 521 - /* Teclast X3 Plus */ 522 - .driver_data = (void *)&teclast_x3_plus_data, 523 - .matches = { 524 - DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), 525 - DMI_MATCH(DMI_PRODUCT_NAME, "X3 Plus"), 526 - DMI_MATCH(DMI_BOARD_NAME, "X3 Plus"), 527 - }, 528 - }, 529 - { 530 - /* I.T.Works TW701 */ 531 - .driver_data = (void *)&surftab_wintron70_st70416_6_data, 532 - .matches = { 533 - DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 534 - DMI_MATCH(DMI_PRODUCT_NAME, "i71c"), 535 - DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"), 536 - }, 537 - }, 538 - { 539 - /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */ 540 - .driver_data = (void *)&chuwi_vi8_data, 541 - .matches = { 542 - DMI_MATCH(DMI_SYS_VENDOR, "YOURS"), 543 - DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"), 544 - }, 545 - }, 546 - { 547 - /* ONDA V891w revision P891WBEBV1B00 aka v1 */ 548 - .driver_data = (void *)&onda_v891w_v1_data, 549 - .matches = { 550 - DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"), 551 - DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"), 552 - DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"), 553 - /* Exact match, different versions need different fw */ 554 - DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"), 555 - }, 556 - }, 557 - { }, 558 - }; 559 - 560 - static const struct silead_ts_dmi_data *silead_ts_data; 561 - 562 - static void silead_ts_dmi_add_props(struct i2c_client *client) 563 - { 564 - struct device *dev = &client->dev; 565 - int error; 566 - 567 - if (has_acpi_companion(dev) && 568 - !strncmp(silead_ts_data->acpi_name, client->name, I2C_NAME_SIZE)) { 569 - error = device_add_properties(dev, silead_ts_data->properties); 570 - if (error) 571 - dev_err(dev, "failed to add properties: %d\n", error); 572 - } 573 - } 574 - 575 - static int silead_ts_dmi_notifier_call(struct notifier_block *nb, 576 - unsigned long action, void *data) 577 - { 578 - struct device *dev = data; 579 - struct i2c_client *client; 580 - 581 - switch (action) { 582 - case BUS_NOTIFY_ADD_DEVICE: 583 - client = i2c_verify_client(dev); 584 - if (client) 585 - silead_ts_dmi_add_props(client); 586 - break; 587 - 588 - default: 589 - break; 590 - } 591 - 592 - return 0; 593 - } 594 - 595 - static struct notifier_block silead_ts_dmi_notifier = { 596 - .notifier_call = silead_ts_dmi_notifier_call, 597 - }; 598 - 599 - static int __init silead_ts_dmi_init(void) 600 - { 601 - const struct dmi_system_id *dmi_id; 602 - int error; 603 - 604 - dmi_id = dmi_first_match(silead_ts_dmi_table); 605 - if (!dmi_id) 606 - return 0; /* Not an error */ 607 - 608 - silead_ts_data = dmi_id->driver_data; 609 - 610 - error = bus_register_notifier(&i2c_bus_type, &silead_ts_dmi_notifier); 611 - if (error) 612 - pr_err("%s: failed to register i2c bus notifier: %d\n", 613 - __func__, error); 614 - 615 - return error; 616 - } 617 - 618 - /* 619 - * We are registering out notifier after i2c core is initialized and i2c bus 620 - * itself is ready (which happens at postcore initcall level), but before 621 - * ACPI starts enumerating devices (at subsys initcall level). 622 - */ 623 - arch_initcall(silead_ts_dmi_init);
+80 -55
drivers/platform/x86/thinkpad_acpi.c
··· 336 336 u32 second_fan:1; 337 337 u32 beep_needs_two_args:1; 338 338 u32 mixer_no_level_control:1; 339 + u32 battery_force_primary:1; 339 340 u32 input_device_registered:1; 340 341 u32 platform_drv_registered:1; 341 342 u32 platform_drv_attrs_registered:1; ··· 345 344 u32 sensors_pdev_attrs_registered:1; 346 345 u32 hotkey_poll_active:1; 347 346 u32 has_adaptive_kbd:1; 348 - u32 battery:1; 349 347 } tp_features; 350 348 351 349 static struct { ··· 359 359 char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ 360 360 char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ 361 361 362 - u16 bios_model; /* 1Y = 0x5931, 0 = unknown */ 363 - u16 ec_model; 364 - u16 bios_release; /* 1ZETK1WW = 0x314b, 0 = unknown */ 362 + u32 bios_model; /* 1Y = 0x3159, 0 = unknown */ 363 + u32 ec_model; 364 + u16 bios_release; /* 1ZETK1WW = 0x4b31, 0 = unknown */ 365 365 u16 ec_release; 366 366 367 367 char *model_str; /* ThinkPad T43 */ ··· 445 445 /* 446 446 * Quirk handling helpers 447 447 * 448 - * ThinkPad IDs and versions seen in the field so far 449 - * are two-characters from the set [0-9A-Z], i.e. base 36. 448 + * ThinkPad IDs and versions seen in the field so far are 449 + * two or three characters from the set [0-9A-Z], i.e. base 36. 450 450 * 451 451 * We use values well outside that range as specials. 452 452 */ 453 453 454 - #define TPACPI_MATCH_ANY 0xffffU 454 + #define TPACPI_MATCH_ANY 0xffffffffU 455 + #define TPACPI_MATCH_ANY_VERSION 0xffffU 455 456 #define TPACPI_MATCH_UNKNOWN 0U 456 457 457 - /* TPID('1', 'Y') == 0x5931 */ 458 - #define TPID(__c1, __c2) (((__c2) << 8) | (__c1)) 458 + /* TPID('1', 'Y') == 0x3159 */ 459 + #define TPID(__c1, __c2) (((__c1) << 8) | (__c2)) 460 + #define TPID3(__c1, __c2, __c3) (((__c1) << 16) | ((__c2) << 8) | (__c3)) 461 + #define TPVER TPID 459 462 460 463 #define TPACPI_Q_IBM(__id1, __id2, __quirk) \ 461 464 { .vendor = PCI_VENDOR_ID_IBM, \ ··· 472 469 .ec = TPACPI_MATCH_ANY, \ 473 470 .quirks = (__quirk) } 474 471 472 + #define TPACPI_Q_LNV3(__id1, __id2, __id3, __quirk) \ 473 + { .vendor = PCI_VENDOR_ID_LENOVO, \ 474 + .bios = TPID3(__id1, __id2, __id3), \ 475 + .ec = TPACPI_MATCH_ANY, \ 476 + .quirks = (__quirk) } 477 + 475 478 #define TPACPI_QEC_LNV(__id1, __id2, __quirk) \ 476 479 { .vendor = PCI_VENDOR_ID_LENOVO, \ 477 480 .bios = TPACPI_MATCH_ANY, \ ··· 486 477 487 478 struct tpacpi_quirk { 488 479 unsigned int vendor; 489 - u16 bios; 490 - u16 ec; 480 + u32 bios; 481 + u32 ec; 491 482 unsigned long quirks; 492 483 }; 493 484 ··· 1657 1648 { .vendor = (__v), \ 1658 1649 .bios = TPID(__id1, __id2), \ 1659 1650 .ec = TPACPI_MATCH_ANY, \ 1660 - .quirks = TPACPI_MATCH_ANY << 16 \ 1661 - | (__bv1) << 8 | (__bv2) } 1651 + .quirks = TPACPI_MATCH_ANY_VERSION << 16 \ 1652 + | TPVER(__bv1, __bv2) } 1662 1653 1663 1654 #define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \ 1664 1655 __eid, __ev1, __ev2) \ 1665 1656 { .vendor = (__v), \ 1666 1657 .bios = TPID(__bid1, __bid2), \ 1667 1658 .ec = __eid, \ 1668 - .quirks = (__ev1) << 24 | (__ev2) << 16 \ 1669 - | (__bv1) << 8 | (__bv2) } 1659 + .quirks = TPVER(__ev1, __ev2) << 16 \ 1660 + | TPVER(__bv1, __bv2) } 1670 1661 1671 1662 #define TPV_QI0(__id1, __id2, __bv1, __bv2) \ 1672 1663 TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2) ··· 1808 1799 /* note that unknown versions are set to 0x0000 and we use that */ 1809 1800 if ((bios_version > thinkpad_id.bios_release) || 1810 1801 (ec_version > thinkpad_id.ec_release && 1811 - ec_version != TPACPI_MATCH_ANY)) { 1802 + ec_version != TPACPI_MATCH_ANY_VERSION)) { 1812 1803 /* 1813 1804 * The changelogs would let us track down the exact 1814 1805 * reason, but it is just too much of a pain to track ··· 1938 1929 /* first new observed key (star, favorites) is 0x1311 */ 1939 1930 TP_ACPI_HOTKEYSCAN_STAR = 69, 1940 1931 TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL2, 1941 - TP_ACPI_HOTKEYSCAN_UNK25, 1932 + TP_ACPI_HOTKEYSCAN_CALCULATOR, 1942 1933 TP_ACPI_HOTKEYSCAN_BLUETOOTH, 1943 1934 TP_ACPI_HOTKEYSCAN_KEYBOARD, 1944 1935 ··· 3459 3450 3460 3451 KEY_FAVORITES, /* Favorite app, 0x311 */ 3461 3452 KEY_RESERVED, /* Clipping tool */ 3462 - KEY_RESERVED, 3453 + KEY_CALC, /* Calculator (above numpad, P52) */ 3463 3454 KEY_BLUETOOTH, /* Bluetooth */ 3464 3455 KEY_KEYBOARD /* Keyboard, 0x315 */ 3465 3456 }, ··· 9375 9366 { 9376 9367 int ret = 0; 9377 9368 9378 - memset(&battery_info, 0, sizeof(struct tpacpi_battery_driver_data)); 9369 + memset(&battery_info.batteries[battery], 0, 9370 + sizeof(battery_info.batteries[battery])); 9371 + 9379 9372 /* 9380 9373 * 1) Get the current start threshold 9381 9374 * 2) Check for support ··· 9432 9421 static int tpacpi_battery_get_id(const char *battery_name) 9433 9422 { 9434 9423 9435 - if (strcmp(battery_name, "BAT0") == 0) 9424 + if (strcmp(battery_name, "BAT0") == 0 || 9425 + tp_features.battery_force_primary) 9436 9426 return BAT_PRIMARY; 9437 9427 if (strcmp(battery_name, "BAT1") == 0) 9438 9428 return BAT_SECONDARY; ··· 9609 9597 9610 9598 /* Subdriver init/exit */ 9611 9599 9600 + static const struct tpacpi_quirk battery_quirk_table[] __initconst = { 9601 + /* 9602 + * Individual addressing is broken on models that expose the 9603 + * primary battery as BAT1. 9604 + */ 9605 + TPACPI_Q_LNV('J', '7', true), /* B5400 */ 9606 + TPACPI_Q_LNV('J', 'I', true), /* Thinkpad 11e */ 9607 + TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */ 9608 + TPACPI_Q_LNV3('R', '0', 'C', true), /* Thinkpad 13 */ 9609 + TPACPI_Q_LNV3('R', '0', 'J', true), /* Thinkpad 13 gen 2 */ 9610 + }; 9611 + 9612 9612 static int __init tpacpi_battery_init(struct ibm_init_struct *ibm) 9613 9613 { 9614 + memset(&battery_info, 0, sizeof(battery_info)); 9615 + 9616 + tp_features.battery_force_primary = tpacpi_check_quirks( 9617 + battery_quirk_table, 9618 + ARRAY_SIZE(battery_quirk_table)); 9619 + 9614 9620 battery_hook_register(&battery_hook); 9615 9621 return 0; 9616 9622 } ··· 9839 9809 9840 9810 /* Probing */ 9841 9811 9842 - static bool __pure __init tpacpi_is_fw_digit(const char c) 9812 + static char __init tpacpi_parse_fw_id(const char * const s, 9813 + u32 *model, u16 *release) 9843 9814 { 9844 - return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'); 9845 - } 9815 + int i; 9846 9816 9847 - static bool __pure __init tpacpi_is_valid_fw_id(const char * const s, 9848 - const char t) 9849 - { 9817 + if (!s || strlen(s) < 8) 9818 + goto invalid; 9819 + 9820 + for (i = 0; i < 8; i++) 9821 + if (!((s[i] >= '0' && s[i] <= '9') || 9822 + (s[i] >= 'A' && s[i] <= 'Z'))) 9823 + goto invalid; 9824 + 9850 9825 /* 9851 9826 * Most models: xxyTkkWW (#.##c) 9852 9827 * Ancient 570/600 and -SL lacks (#.##c) 9853 9828 */ 9854 - if (s && strlen(s) >= 8 && 9855 - tpacpi_is_fw_digit(s[0]) && 9856 - tpacpi_is_fw_digit(s[1]) && 9857 - s[2] == t && 9858 - (s[3] == 'T' || s[3] == 'N') && 9859 - tpacpi_is_fw_digit(s[4]) && 9860 - tpacpi_is_fw_digit(s[5])) 9861 - return true; 9829 + if (s[3] == 'T' || s[3] == 'N') { 9830 + *model = TPID(s[0], s[1]); 9831 + *release = TPVER(s[4], s[5]); 9832 + return s[2]; 9862 9833 9863 9834 /* New models: xxxyTkkW (#.##c); T550 and some others */ 9864 - return s && strlen(s) >= 8 && 9865 - tpacpi_is_fw_digit(s[0]) && 9866 - tpacpi_is_fw_digit(s[1]) && 9867 - tpacpi_is_fw_digit(s[2]) && 9868 - s[3] == t && 9869 - (s[4] == 'T' || s[4] == 'N') && 9870 - tpacpi_is_fw_digit(s[5]) && 9871 - tpacpi_is_fw_digit(s[6]); 9835 + } else if (s[4] == 'T' || s[4] == 'N') { 9836 + *model = TPID3(s[0], s[1], s[2]); 9837 + *release = TPVER(s[5], s[6]); 9838 + return s[3]; 9839 + } 9840 + 9841 + invalid: 9842 + return '\0'; 9872 9843 } 9873 9844 9874 9845 /* returns 0 - probe ok, or < 0 - probe error. ··· 9881 9850 const struct dmi_device *dev = NULL; 9882 9851 char ec_fw_string[18]; 9883 9852 char const *s; 9853 + char t; 9884 9854 9885 9855 if (!tp) 9886 9856 return -EINVAL; ··· 9901 9869 return -ENOMEM; 9902 9870 9903 9871 /* Really ancient ThinkPad 240X will fail this, which is fine */ 9904 - if (!(tpacpi_is_valid_fw_id(tp->bios_version_str, 'E') || 9905 - tpacpi_is_valid_fw_id(tp->bios_version_str, 'C'))) 9872 + t = tpacpi_parse_fw_id(tp->bios_version_str, 9873 + &tp->bios_model, &tp->bios_release); 9874 + if (t != 'E' && t != 'C') 9906 9875 return 0; 9907 - 9908 - tp->bios_model = tp->bios_version_str[0] 9909 - | (tp->bios_version_str[1] << 8); 9910 - tp->bios_release = (tp->bios_version_str[4] << 8) 9911 - | tp->bios_version_str[5]; 9912 9876 9913 9877 /* 9914 9878 * ThinkPad T23 or newer, A31 or newer, R50e or newer, ··· 9924 9896 if (!tp->ec_version_str) 9925 9897 return -ENOMEM; 9926 9898 9927 - if (tpacpi_is_valid_fw_id(ec_fw_string, 'H')) { 9928 - tp->ec_model = ec_fw_string[0] 9929 - | (ec_fw_string[1] << 8); 9930 - tp->ec_release = (ec_fw_string[4] << 8) 9931 - | ec_fw_string[5]; 9932 - } else { 9899 + t = tpacpi_parse_fw_id(ec_fw_string, 9900 + &tp->ec_model, &tp->ec_release); 9901 + if (t != 'H') { 9933 9902 pr_notice("ThinkPad firmware release %s doesn't match the known patterns\n", 9934 9903 ec_fw_string); 9935 9904 pr_notice("please report this to %s\n",
+24 -9
drivers/platform/x86/toshiba_acpi.c
··· 34 34 #define TOSHIBA_ACPI_VERSION "0.24" 35 35 #define PROC_INTERFACE_VERSION 1 36 36 37 + #include <linux/compiler.h> 37 38 #include <linux/kernel.h> 38 39 #include <linux/module.h> 39 40 #include <linux/moduleparam.h> ··· 1683 1682 .write = keys_proc_write, 1684 1683 }; 1685 1684 1686 - static int version_proc_show(struct seq_file *m, void *v) 1685 + static int __maybe_unused version_proc_show(struct seq_file *m, void *v) 1687 1686 { 1688 1687 seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION); 1689 1688 seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION); ··· 1837 1836 return ret; 1838 1837 1839 1838 toshiba->kbd_mode = mode; 1839 + toshiba_acpi->kbd_mode = mode; 1840 1840 1841 1841 /* 1842 1842 * Some laptop models with the second generation backlit ··· 1854 1852 * event via genetlink. 1855 1853 */ 1856 1854 if (toshiba->kbd_type == 2 && 1857 - !toshiba_acpi->kbd_event_generated) 1855 + !toshiba->kbd_event_generated) 1858 1856 schedule_work(&kbd_bl_work); 1859 1857 } 1860 1858 ··· 2415 2413 2416 2414 static void toshiba_acpi_kbd_bl_work(struct work_struct *work) 2417 2415 { 2418 - struct acpi_device *acpi_dev = toshiba_acpi->acpi_dev; 2419 - 2420 2416 /* Update the sysfs entries */ 2421 - if (sysfs_update_group(&acpi_dev->dev.kobj, 2417 + if (sysfs_update_group(&toshiba_acpi->acpi_dev->dev.kobj, 2422 2418 &toshiba_attr_group)) 2423 2419 pr_err("Unable to update sysfs entries\n"); 2424 2420 2421 + /* Notify LED subsystem about keyboard backlight change */ 2422 + if (toshiba_acpi->kbd_type == 2 && 2423 + toshiba_acpi->kbd_mode != SCI_KBD_MODE_AUTO) 2424 + led_classdev_notify_brightness_hw_changed(&toshiba_acpi->kbd_led, 2425 + (toshiba_acpi->kbd_mode == SCI_KBD_MODE_ON) ? 2426 + LED_FULL : LED_OFF); 2427 + 2425 2428 /* Emulate the keyboard backlight event */ 2426 - acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class, 2427 - dev_name(&acpi_dev->dev), 2429 + acpi_bus_generate_netlink_event(toshiba_acpi->acpi_dev->pnp.device_class, 2430 + dev_name(&toshiba_acpi->acpi_dev->dev), 2428 2431 0x92, 0); 2429 2432 } 2430 2433 ··· 3126 3119 /* 3127 3120 * Only register the LED if KBD illumination is supported 3128 3121 * and the keyboard backlight operation mode is set to FN-Z 3122 + * or we detect a second gen keyboard backlight 3129 3123 */ 3130 - if (dev->kbd_illum_supported && dev->kbd_mode == SCI_KBD_MODE_FNZ) { 3124 + if (dev->kbd_illum_supported && 3125 + (dev->kbd_mode == SCI_KBD_MODE_FNZ || dev->kbd_type == 2)) { 3131 3126 dev->kbd_led.name = "toshiba::kbd_backlight"; 3127 + dev->kbd_led.flags = LED_BRIGHT_HW_CHANGED; 3132 3128 dev->kbd_led.max_brightness = 1; 3133 3129 dev->kbd_led.brightness_set = toshiba_kbd_backlight_set; 3134 3130 dev->kbd_led.brightness_get = toshiba_kbd_backlight_get; ··· 3247 3237 pr_info("SATA power event received %x\n", event); 3248 3238 break; 3249 3239 case 0x92: /* Keyboard backlight mode changed */ 3250 - toshiba_acpi->kbd_event_generated = true; 3240 + dev->kbd_event_generated = true; 3251 3241 /* Update sysfs entries */ 3252 3242 if (sysfs_update_group(&acpi_dev->dev.kobj, 3253 3243 &toshiba_attr_group)) 3254 3244 pr_err("Unable to update sysfs entries\n"); 3245 + /* Notify LED subsystem about keyboard backlight change */ 3246 + if (dev->kbd_type == 2 && dev->kbd_mode != SCI_KBD_MODE_AUTO) 3247 + led_classdev_notify_brightness_hw_changed(&dev->kbd_led, 3248 + (dev->kbd_mode == SCI_KBD_MODE_ON) ? 3249 + LED_FULL : LED_OFF); 3255 3250 break; 3256 3251 case 0x85: /* Unknown */ 3257 3252 case 0x8d: /* Unknown */
+754
drivers/platform/x86/touchscreen_dmi.c
··· 1 + /* 2 + * Touchscreen driver DMI based configuration code 3 + * 4 + * Copyright (c) 2017 Red Hat Inc. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * Red Hat authors: 12 + * Hans de Goede <hdegoede@redhat.com> 13 + */ 14 + 15 + #include <linux/acpi.h> 16 + #include <linux/device.h> 17 + #include <linux/dmi.h> 18 + #include <linux/i2c.h> 19 + #include <linux/notifier.h> 20 + #include <linux/property.h> 21 + #include <linux/string.h> 22 + 23 + struct ts_dmi_data { 24 + const char *acpi_name; 25 + const struct property_entry *properties; 26 + }; 27 + 28 + /* NOTE: Please keep all entries sorted alphabetically */ 29 + 30 + static const struct property_entry chuwi_hi8_props[] = { 31 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1665), 32 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), 33 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 34 + PROPERTY_ENTRY_BOOL("silead,home-button"), 35 + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"), 36 + { } 37 + }; 38 + 39 + static const struct ts_dmi_data chuwi_hi8_data = { 40 + .acpi_name = "MSSL0001:00", 41 + .properties = chuwi_hi8_props, 42 + }; 43 + 44 + static const struct property_entry chuwi_hi8_pro_props[] = { 45 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1728), 46 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1148), 47 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 48 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"), 49 + PROPERTY_ENTRY_BOOL("silead,home-button"), 50 + { } 51 + }; 52 + 53 + static const struct ts_dmi_data chuwi_hi8_pro_data = { 54 + .acpi_name = "MSSL1680:00", 55 + .properties = chuwi_hi8_pro_props, 56 + }; 57 + 58 + static const struct property_entry chuwi_vi8_props[] = { 59 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1724), 60 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), 61 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 62 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-vi8.fw"), 63 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 64 + PROPERTY_ENTRY_BOOL("silead,home-button"), 65 + { } 66 + }; 67 + 68 + static const struct ts_dmi_data chuwi_vi8_data = { 69 + .acpi_name = "MSSL1680:00", 70 + .properties = chuwi_vi8_props, 71 + }; 72 + 73 + static const struct property_entry chuwi_vi10_props[] = { 74 + PROPERTY_ENTRY_U32("touchscreen-min-x", 0), 75 + PROPERTY_ENTRY_U32("touchscreen-min-y", 4), 76 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1858), 77 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1280), 78 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-vi10.fw"), 79 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 80 + PROPERTY_ENTRY_BOOL("silead,home-button"), 81 + { } 82 + }; 83 + 84 + static const struct ts_dmi_data chuwi_vi10_data = { 85 + .acpi_name = "MSSL0002:00", 86 + .properties = chuwi_vi10_props, 87 + }; 88 + 89 + static const struct property_entry connect_tablet9_props[] = { 90 + PROPERTY_ENTRY_U32("touchscreen-min-x", 9), 91 + PROPERTY_ENTRY_U32("touchscreen-min-y", 8), 92 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1664), 93 + PROPERTY_ENTRY_U32("touchscreen-size-y", 878), 94 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 95 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 96 + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-connect-tablet9.fw"), 97 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 98 + { } 99 + }; 100 + 101 + static const struct ts_dmi_data connect_tablet9_data = { 102 + .acpi_name = "MSSL1680:00", 103 + .properties = connect_tablet9_props, 104 + }; 105 + 106 + static const struct property_entry cube_iwork8_air_props[] = { 107 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1660), 108 + PROPERTY_ENTRY_U32("touchscreen-size-y", 900), 109 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 110 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"), 111 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 112 + { } 113 + }; 114 + 115 + static const struct ts_dmi_data cube_iwork8_air_data = { 116 + .acpi_name = "MSSL1680:00", 117 + .properties = cube_iwork8_air_props, 118 + }; 119 + 120 + static const struct property_entry cube_knote_i1101_props[] = { 121 + PROPERTY_ENTRY_U32("touchscreen-min-x", 20), 122 + PROPERTY_ENTRY_U32("touchscreen-min-y", 22), 123 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1961), 124 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1513), 125 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-cube-knote-i1101.fw"), 126 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 127 + PROPERTY_ENTRY_BOOL("silead,home-button"), 128 + { } 129 + }; 130 + 131 + static const struct ts_dmi_data cube_knote_i1101_data = { 132 + .acpi_name = "MSSL1680:00", 133 + .properties = cube_knote_i1101_props, 134 + }; 135 + 136 + static const struct property_entry dexp_ursus_7w_props[] = { 137 + PROPERTY_ENTRY_U32("touchscreen-size-x", 890), 138 + PROPERTY_ENTRY_U32("touchscreen-size-y", 630), 139 + PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"), 140 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 141 + PROPERTY_ENTRY_BOOL("silead,home-button"), 142 + { } 143 + }; 144 + 145 + static const struct ts_dmi_data dexp_ursus_7w_data = { 146 + .acpi_name = "MSSL1680:00", 147 + .properties = dexp_ursus_7w_props, 148 + }; 149 + 150 + static const struct property_entry digma_citi_e200_props[] = { 151 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), 152 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1500), 153 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 154 + PROPERTY_ENTRY_STRING("firmware-name", 155 + "gsl1686-digma_citi_e200.fw"), 156 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 157 + PROPERTY_ENTRY_BOOL("silead,home-button"), 158 + { } 159 + }; 160 + 161 + static const struct ts_dmi_data digma_citi_e200_data = { 162 + .acpi_name = "MSSL1680:00", 163 + .properties = digma_citi_e200_props, 164 + }; 165 + 166 + static const struct property_entry gp_electronic_t701_props[] = { 167 + PROPERTY_ENTRY_U32("touchscreen-size-x", 960), 168 + PROPERTY_ENTRY_U32("touchscreen-size-y", 640), 169 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 170 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 171 + PROPERTY_ENTRY_STRING("firmware-name", 172 + "gsl1680-gp-electronic-t701.fw"), 173 + { } 174 + }; 175 + 176 + static const struct ts_dmi_data gp_electronic_t701_data = { 177 + .acpi_name = "MSSL1680:00", 178 + .properties = gp_electronic_t701_props, 179 + }; 180 + 181 + static const struct property_entry itworks_tw891_props[] = { 182 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1600), 183 + PROPERTY_ENTRY_U32("touchscreen-size-y", 890), 184 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 185 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 186 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"), 187 + { } 188 + }; 189 + 190 + static const struct ts_dmi_data itworks_tw891_data = { 191 + .acpi_name = "MSSL1680:00", 192 + .properties = itworks_tw891_props, 193 + }; 194 + 195 + static const struct property_entry jumper_ezpad_6_pro_props[] = { 196 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), 197 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1500), 198 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"), 199 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 200 + PROPERTY_ENTRY_BOOL("silead,home-button"), 201 + { } 202 + }; 203 + 204 + static const struct ts_dmi_data jumper_ezpad_6_pro_data = { 205 + .acpi_name = "MSSL1680:00", 206 + .properties = jumper_ezpad_6_pro_props, 207 + }; 208 + 209 + static const struct property_entry jumper_ezpad_mini3_props[] = { 210 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1700), 211 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1150), 212 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 213 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"), 214 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 215 + { } 216 + }; 217 + 218 + static const struct ts_dmi_data jumper_ezpad_mini3_data = { 219 + .acpi_name = "MSSL1680:00", 220 + .properties = jumper_ezpad_mini3_props, 221 + }; 222 + 223 + static const struct property_entry onda_obook_20_plus_props[] = { 224 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1728), 225 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1148), 226 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 227 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 228 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 229 + PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-obook-20-plus.fw"), 230 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 231 + PROPERTY_ENTRY_BOOL("silead,home-button"), 232 + { } 233 + }; 234 + 235 + static const struct ts_dmi_data onda_obook_20_plus_data = { 236 + .acpi_name = "MSSL1680:00", 237 + .properties = onda_obook_20_plus_props, 238 + }; 239 + 240 + static const struct property_entry onda_v820w_32g_props[] = { 241 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1665), 242 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), 243 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 244 + PROPERTY_ENTRY_STRING("firmware-name", 245 + "gsl1680-onda-v820w-32g.fw"), 246 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 247 + PROPERTY_ENTRY_BOOL("silead,home-button"), 248 + { } 249 + }; 250 + 251 + static const struct ts_dmi_data onda_v820w_32g_data = { 252 + .acpi_name = "MSSL1680:00", 253 + .properties = onda_v820w_32g_props, 254 + }; 255 + 256 + static const struct property_entry onda_v891w_v1_props[] = { 257 + PROPERTY_ENTRY_U32("touchscreen-min-x", 46), 258 + PROPERTY_ENTRY_U32("touchscreen-min-y", 8), 259 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1676), 260 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1130), 261 + PROPERTY_ENTRY_STRING("firmware-name", 262 + "gsl3680-onda-v891w-v1.fw"), 263 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 264 + PROPERTY_ENTRY_BOOL("silead,home-button"), 265 + { } 266 + }; 267 + 268 + static const struct ts_dmi_data onda_v891w_v1_data = { 269 + .acpi_name = "MSSL1680:00", 270 + .properties = onda_v891w_v1_props, 271 + }; 272 + 273 + static const struct property_entry onda_v891w_v3_props[] = { 274 + PROPERTY_ENTRY_U32("touchscreen-min-x", 35), 275 + PROPERTY_ENTRY_U32("touchscreen-min-y", 15), 276 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1625), 277 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1135), 278 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 279 + PROPERTY_ENTRY_STRING("firmware-name", 280 + "gsl3676-onda-v891w-v3.fw"), 281 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 282 + PROPERTY_ENTRY_BOOL("silead,home-button"), 283 + { } 284 + }; 285 + 286 + static const struct ts_dmi_data onda_v891w_v3_data = { 287 + .acpi_name = "MSSL1680:00", 288 + .properties = onda_v891w_v3_props, 289 + }; 290 + 291 + static const struct property_entry pipo_w2s_props[] = { 292 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1660), 293 + PROPERTY_ENTRY_U32("touchscreen-size-y", 880), 294 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 295 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 296 + PROPERTY_ENTRY_STRING("firmware-name", 297 + "gsl1680-pipo-w2s.fw"), 298 + { } 299 + }; 300 + 301 + static const struct ts_dmi_data pipo_w2s_data = { 302 + .acpi_name = "MSSL1680:00", 303 + .properties = pipo_w2s_props, 304 + }; 305 + 306 + static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = { 307 + PROPERTY_ENTRY_U32("touchscreen-min-x", 32), 308 + PROPERTY_ENTRY_U32("touchscreen-min-y", 16), 309 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1692), 310 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1146), 311 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 312 + PROPERTY_ENTRY_STRING("firmware-name", 313 + "gsl3680-pov-mobii-wintab-p800w-v20.fw"), 314 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 315 + PROPERTY_ENTRY_BOOL("silead,home-button"), 316 + { } 317 + }; 318 + 319 + static const struct ts_dmi_data pov_mobii_wintab_p800w_v20_data = { 320 + .acpi_name = "MSSL1680:00", 321 + .properties = pov_mobii_wintab_p800w_v20_props, 322 + }; 323 + 324 + static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = { 325 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1800), 326 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1150), 327 + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), 328 + PROPERTY_ENTRY_STRING("firmware-name", 329 + "gsl3692-pov-mobii-wintab-p800w.fw"), 330 + PROPERTY_ENTRY_BOOL("silead,home-button"), 331 + { } 332 + }; 333 + 334 + static const struct ts_dmi_data pov_mobii_wintab_p800w_v21_data = { 335 + .acpi_name = "MSSL1680:00", 336 + .properties = pov_mobii_wintab_p800w_v21_props, 337 + }; 338 + 339 + static const struct property_entry teclast_x3_plus_props[] = { 340 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1980), 341 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1500), 342 + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-teclast-x3-plus.fw"), 343 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 344 + PROPERTY_ENTRY_BOOL("silead,home-button"), 345 + { } 346 + }; 347 + 348 + static const struct ts_dmi_data teclast_x3_plus_data = { 349 + .acpi_name = "MSSL1680:00", 350 + .properties = teclast_x3_plus_props, 351 + }; 352 + 353 + static const struct property_entry teclast_x98plus2_props[] = { 354 + PROPERTY_ENTRY_U32("touchscreen-size-x", 2048), 355 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1280), 356 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), 357 + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), 358 + PROPERTY_ENTRY_STRING("firmware-name", 359 + "gsl1686-teclast_x98plus2.fw"), 360 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 361 + { } 362 + }; 363 + 364 + static const struct ts_dmi_data teclast_x98plus2_data = { 365 + .acpi_name = "MSSL1680:00", 366 + .properties = teclast_x98plus2_props, 367 + }; 368 + 369 + static const struct property_entry trekstor_primebook_c13_props[] = { 370 + PROPERTY_ENTRY_U32("touchscreen-size-x", 2624), 371 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1920), 372 + PROPERTY_ENTRY_STRING("firmware-name", 373 + "gsl1680-trekstor-primebook-c13.fw"), 374 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 375 + PROPERTY_ENTRY_BOOL("silead,home-button"), 376 + { } 377 + }; 378 + 379 + static const struct ts_dmi_data trekstor_primebook_c13_data = { 380 + .acpi_name = "MSSL1680:00", 381 + .properties = trekstor_primebook_c13_props, 382 + }; 383 + 384 + static const struct property_entry trekstor_surftab_twin_10_1_props[] = { 385 + PROPERTY_ENTRY_U32("touchscreen-size-x", 1900), 386 + PROPERTY_ENTRY_U32("touchscreen-size-y", 1280), 387 + PROPERTY_ENTRY_U32("touchscreen-inverted-y", 1), 388 + PROPERTY_ENTRY_STRING("firmware-name", 389 + "gsl3670-surftab-twin-10-1-st10432-8.fw"), 390 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 391 + { } 392 + }; 393 + 394 + static const struct ts_dmi_data trekstor_surftab_twin_10_1_data = { 395 + .acpi_name = "MSSL1680:00", 396 + .properties = trekstor_surftab_twin_10_1_props, 397 + }; 398 + 399 + static const struct property_entry trekstor_surftab_wintron70_props[] = { 400 + PROPERTY_ENTRY_U32("touchscreen-size-x", 884), 401 + PROPERTY_ENTRY_U32("touchscreen-size-y", 632), 402 + PROPERTY_ENTRY_STRING("firmware-name", 403 + "gsl1686-surftab-wintron70-st70416-6.fw"), 404 + PROPERTY_ENTRY_U32("silead,max-fingers", 10), 405 + PROPERTY_ENTRY_BOOL("silead,home-button"), 406 + { } 407 + }; 408 + 409 + static const struct ts_dmi_data trekstor_surftab_wintron70_data = { 410 + .acpi_name = "MSSL1680:00", 411 + .properties = trekstor_surftab_wintron70_props, 412 + }; 413 + 414 + /* NOTE: Please keep this table sorted alphabetically */ 415 + static const struct dmi_system_id touchscreen_dmi_table[] = { 416 + { 417 + /* Chuwi Hi8 */ 418 + .driver_data = (void *)&chuwi_hi8_data, 419 + .matches = { 420 + DMI_MATCH(DMI_SYS_VENDOR, "ilife"), 421 + DMI_MATCH(DMI_PRODUCT_NAME, "S806"), 422 + }, 423 + }, 424 + { 425 + /* Chuwi Hi8 (H1D_S806_206) */ 426 + .driver_data = (void *)&chuwi_hi8_data, 427 + .matches = { 428 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 429 + DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"), 430 + DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"), 431 + }, 432 + }, 433 + { 434 + /* Chuwi Hi8 Pro (CWI513) */ 435 + .driver_data = (void *)&chuwi_hi8_pro_data, 436 + .matches = { 437 + DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"), 438 + DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"), 439 + }, 440 + }, 441 + { 442 + /* Chuwi Vi8 (CWI506) */ 443 + .driver_data = (void *)&chuwi_vi8_data, 444 + .matches = { 445 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 446 + DMI_MATCH(DMI_PRODUCT_NAME, "i86"), 447 + DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"), 448 + }, 449 + }, 450 + { 451 + /* Chuwi Vi10 (CWI505) */ 452 + .driver_data = (void *)&chuwi_vi10_data, 453 + .matches = { 454 + DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), 455 + DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"), 456 + DMI_MATCH(DMI_SYS_VENDOR, "ilife"), 457 + DMI_MATCH(DMI_PRODUCT_NAME, "S165"), 458 + }, 459 + }, 460 + { 461 + /* Connect Tablet 9 */ 462 + .driver_data = (void *)&connect_tablet9_data, 463 + .matches = { 464 + DMI_MATCH(DMI_SYS_VENDOR, "Connect"), 465 + DMI_MATCH(DMI_PRODUCT_NAME, "Tablet 9"), 466 + }, 467 + }, 468 + { 469 + /* CUBE iwork8 Air */ 470 + .driver_data = (void *)&cube_iwork8_air_data, 471 + .matches = { 472 + DMI_MATCH(DMI_SYS_VENDOR, "cube"), 473 + DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"), 474 + DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), 475 + }, 476 + }, 477 + { 478 + /* Cube KNote i1101 */ 479 + .driver_data = (void *)&cube_knote_i1101_data, 480 + .matches = { 481 + DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), 482 + DMI_MATCH(DMI_BOARD_NAME, "L1W6_I1101"), 483 + DMI_MATCH(DMI_SYS_VENDOR, "ALLDOCUBE"), 484 + DMI_MATCH(DMI_PRODUCT_NAME, "i1101"), 485 + }, 486 + }, 487 + { 488 + /* DEXP Ursus 7W */ 489 + .driver_data = (void *)&dexp_ursus_7w_data, 490 + .matches = { 491 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 492 + DMI_MATCH(DMI_PRODUCT_NAME, "7W"), 493 + }, 494 + }, 495 + { 496 + /* Digma Citi E200 */ 497 + .driver_data = (void *)&digma_citi_e200_data, 498 + .matches = { 499 + DMI_MATCH(DMI_SYS_VENDOR, "Digma"), 500 + DMI_MATCH(DMI_PRODUCT_NAME, "CITI E200"), 501 + DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), 502 + }, 503 + }, 504 + { 505 + /* GP-electronic T701 */ 506 + .driver_data = (void *)&gp_electronic_t701_data, 507 + .matches = { 508 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 509 + DMI_MATCH(DMI_PRODUCT_NAME, "T701"), 510 + DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"), 511 + }, 512 + }, 513 + { 514 + /* I.T.Works TW701 (same hardware as the Trekstor ST70416-6) */ 515 + .driver_data = (void *)&trekstor_surftab_wintron70_data, 516 + .matches = { 517 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 518 + DMI_MATCH(DMI_PRODUCT_NAME, "i71c"), 519 + DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"), 520 + }, 521 + }, 522 + { 523 + /* I.T.Works TW891 */ 524 + .driver_data = (void *)&itworks_tw891_data, 525 + .matches = { 526 + DMI_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), 527 + DMI_MATCH(DMI_PRODUCT_NAME, "TW891"), 528 + }, 529 + }, 530 + { 531 + /* Jumper EZpad 6 Pro */ 532 + .driver_data = (void *)&jumper_ezpad_6_pro_data, 533 + .matches = { 534 + DMI_MATCH(DMI_SYS_VENDOR, "Jumper"), 535 + DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"), 536 + DMI_MATCH(DMI_BIOS_VERSION, "5.12"), 537 + /* Above matches are too generic, add bios-date match */ 538 + DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"), 539 + }, 540 + }, 541 + { 542 + /* Jumper EZpad mini3 */ 543 + .driver_data = (void *)&jumper_ezpad_mini3_data, 544 + .matches = { 545 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 546 + /* jumperx.T87.KFBNEEA02 with the version-nr dropped */ 547 + DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"), 548 + }, 549 + }, 550 + { 551 + /* Onda oBook 20 Plus */ 552 + .driver_data = (void *)&onda_obook_20_plus_data, 553 + .matches = { 554 + DMI_MATCH(DMI_SYS_VENDOR, "ONDA"), 555 + DMI_MATCH(DMI_PRODUCT_NAME, "OBOOK 20 PLUS"), 556 + }, 557 + }, 558 + { 559 + /* ONDA V820w DualOS */ 560 + .driver_data = (void *)&onda_v820w_32g_data, 561 + .matches = { 562 + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"), 563 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "V820w DualOS") 564 + }, 565 + }, 566 + { 567 + /* ONDA V891w revision P891WBEBV1B00 aka v1 */ 568 + .driver_data = (void *)&onda_v891w_v1_data, 569 + .matches = { 570 + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"), 571 + DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"), 572 + DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"), 573 + /* Exact match, different versions need different fw */ 574 + DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"), 575 + }, 576 + }, 577 + { 578 + /* ONDA V891w Dual OS P891DCF2V1A01274 64GB */ 579 + .driver_data = (void *)&onda_v891w_v3_data, 580 + .matches = { 581 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 582 + DMI_MATCH(DMI_PRODUCT_NAME, "ONDA Tablet"), 583 + DMI_MATCH(DMI_BIOS_VERSION, "ONDA.D890HBBNR0A"), 584 + }, 585 + }, 586 + { 587 + /* Pipo W2S */ 588 + .driver_data = (void *)&pipo_w2s_data, 589 + .matches = { 590 + DMI_MATCH(DMI_SYS_VENDOR, "PIPO"), 591 + DMI_MATCH(DMI_PRODUCT_NAME, "W2S"), 592 + }, 593 + }, 594 + { 595 + /* Ployer Momo7w (same hardware as the Trekstor ST70416-6) */ 596 + .driver_data = (void *)&trekstor_surftab_wintron70_data, 597 + .matches = { 598 + DMI_MATCH(DMI_SYS_VENDOR, "Shenzhen PLOYER"), 599 + DMI_MATCH(DMI_PRODUCT_NAME, "MOMO7W"), 600 + /* Exact match, different versions need different fw */ 601 + DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"), 602 + }, 603 + }, 604 + { 605 + /* Point of View mobii wintab p800w (v2.0) */ 606 + .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data, 607 + .matches = { 608 + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 609 + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 610 + DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"), 611 + /* Above matches are too generic, add bios-date match */ 612 + DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"), 613 + }, 614 + }, 615 + { 616 + /* Point of View mobii wintab p800w (v2.1) */ 617 + .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data, 618 + .matches = { 619 + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 620 + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), 621 + DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"), 622 + /* Above matches are too generic, add bios-date match */ 623 + DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"), 624 + }, 625 + }, 626 + { 627 + /* Teclast X3 Plus */ 628 + .driver_data = (void *)&teclast_x3_plus_data, 629 + .matches = { 630 + DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), 631 + DMI_MATCH(DMI_PRODUCT_NAME, "X3 Plus"), 632 + DMI_MATCH(DMI_BOARD_NAME, "X3 Plus"), 633 + }, 634 + }, 635 + { 636 + /* Teclast X98 Plus II */ 637 + .driver_data = (void *)&teclast_x98plus2_data, 638 + .matches = { 639 + DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"), 640 + DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"), 641 + }, 642 + }, 643 + { 644 + /* Trekstor Primebook C13 */ 645 + .driver_data = (void *)&trekstor_primebook_c13_data, 646 + .matches = { 647 + DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"), 648 + DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"), 649 + }, 650 + }, 651 + { 652 + /* TrekStor SurfTab twin 10.1 ST10432-8 */ 653 + .driver_data = (void *)&trekstor_surftab_twin_10_1_data, 654 + .matches = { 655 + DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"), 656 + DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab twin 10.1"), 657 + }, 658 + }, 659 + { 660 + /* Trekstor Surftab Wintron 7.0 ST70416-6 */ 661 + .driver_data = (void *)&trekstor_surftab_wintron70_data, 662 + .matches = { 663 + DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), 664 + DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"), 665 + /* Exact match, different versions need different fw */ 666 + DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"), 667 + }, 668 + }, 669 + { 670 + /* Trekstor Surftab Wintron 7.0 ST70416-6, newer BIOS */ 671 + .driver_data = (void *)&trekstor_surftab_wintron70_data, 672 + .matches = { 673 + DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"), 674 + DMI_MATCH(DMI_PRODUCT_NAME, 675 + "SurfTab wintron 7.0 ST70416-6"), 676 + /* Exact match, different versions need different fw */ 677 + DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA05"), 678 + }, 679 + }, 680 + { 681 + /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */ 682 + .driver_data = (void *)&chuwi_vi8_data, 683 + .matches = { 684 + DMI_MATCH(DMI_SYS_VENDOR, "YOURS"), 685 + DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"), 686 + }, 687 + }, 688 + { }, 689 + }; 690 + 691 + static const struct ts_dmi_data *ts_data; 692 + 693 + static void ts_dmi_add_props(struct i2c_client *client) 694 + { 695 + struct device *dev = &client->dev; 696 + int error; 697 + 698 + if (has_acpi_companion(dev) && 699 + !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) { 700 + error = device_add_properties(dev, ts_data->properties); 701 + if (error) 702 + dev_err(dev, "failed to add properties: %d\n", error); 703 + } 704 + } 705 + 706 + static int ts_dmi_notifier_call(struct notifier_block *nb, 707 + unsigned long action, void *data) 708 + { 709 + struct device *dev = data; 710 + struct i2c_client *client; 711 + 712 + switch (action) { 713 + case BUS_NOTIFY_ADD_DEVICE: 714 + client = i2c_verify_client(dev); 715 + if (client) 716 + ts_dmi_add_props(client); 717 + break; 718 + 719 + default: 720 + break; 721 + } 722 + 723 + return 0; 724 + } 725 + 726 + static struct notifier_block ts_dmi_notifier = { 727 + .notifier_call = ts_dmi_notifier_call, 728 + }; 729 + 730 + static int __init ts_dmi_init(void) 731 + { 732 + const struct dmi_system_id *dmi_id; 733 + int error; 734 + 735 + dmi_id = dmi_first_match(touchscreen_dmi_table); 736 + if (!dmi_id) 737 + return 0; /* Not an error */ 738 + 739 + ts_data = dmi_id->driver_data; 740 + 741 + error = bus_register_notifier(&i2c_bus_type, &ts_dmi_notifier); 742 + if (error) 743 + pr_err("%s: failed to register i2c bus notifier: %d\n", 744 + __func__, error); 745 + 746 + return error; 747 + } 748 + 749 + /* 750 + * We are registering out notifier after i2c core is initialized and i2c bus 751 + * itself is ready (which happens at postcore initcall level), but before 752 + * ACPI starts enumerating devices (at subsys initcall level). 753 + */ 754 + arch_initcall(ts_dmi_init);
+3 -6
drivers/platform/x86/wmi.c
··· 895 895 struct wmi_driver *wdriver = 896 896 container_of(dev->driver, struct wmi_driver, driver); 897 897 int ret = 0; 898 - int count; 899 898 char *buf; 900 899 901 900 if (ACPI_FAILURE(wmi_method_enable(wblock, 1))) ··· 916 917 goto probe_failure; 917 918 } 918 919 919 - count = get_order(wblock->req_buf_size); 920 - wblock->handler_data = (void *)__get_free_pages(GFP_KERNEL, 921 - count); 920 + wblock->handler_data = kmalloc(wblock->req_buf_size, 921 + GFP_KERNEL); 922 922 if (!wblock->handler_data) { 923 923 ret = -ENOMEM; 924 924 goto probe_failure; ··· 962 964 if (wdriver->filter_callback) { 963 965 misc_deregister(&wblock->char_dev); 964 966 kfree(wblock->char_dev.name); 965 - free_pages((unsigned long)wblock->handler_data, 966 - get_order(wblock->req_buf_size)); 967 + kfree(wblock->handler_data); 967 968 } 968 969 969 970 if (wdriver->remove)