]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
Merge tag 'platform-drivers-x86-v4.20-1' of git://git.infradead.org/linux-platform...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Nov 2018 15:42:21 +0000 (08:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Nov 2018 15:42:21 +0000 (08:42 -0700)
Pull x86 platform driver updates from Darren Hart:

 - Move the Dell dcdbas and dell_rbu drivers into platform/drivers/x86
   as they are closely coupled with other drivers in this location.

 - Improve _init* usage for acerhdf and fix some usage issues with
   messages and module parameters.

 - Simplify asus-wmi by calling ACPI/WMI methods directly, eliminating
   workqueue overhead, eliminate double reporting of keyboard backlight.

 - Fix wake from USB failure on Bay Trail devices (intel_int0002_vgpio).

 - Notify intel_telemetry users when IPC1 device is not enabled.

 - Update various drivers with new laptop model IDs.

 - Update several intel drivers to use SPDX identifers and order headers
   alphabetically.

* tag 'platform-drivers-x86-v4.20-1' of git://git.infradead.org/linux-platform-drivers-x86: (64 commits)
  HID: asus: only support backlight when it's not driven by WMI
  platform/x86: asus-wmi: export function for evaluating WMI methods
  platform/x86: asus-wmi: Only notify kbd LED hw_change by fn-key pressed
  platform/x86: wmi: declare device_type structure as constant
  platform/x86: ideapad: Add Y530-15ICH to no_hw_rfkill
  platform/x86: Add Intel AtomISP2 dummy / power-management driver
  platform/x86: touchscreen_dmi: Add min-x and min-y settings for various models
  platform/x86: touchscreen_dmi: Add info for the Onda V80 Plus v3 tablet
  platform/x86: touchscreen_dmi: Add info for the Trekstor Primetab T13B tablet
  platform/x86: intel_telemetry: Get rid of custom macro
  platform/x86: intel_telemetry: report debugfs failure
  MAINTAINERS: intel_telemetry: Update maintainers info
  platform/x86: Add LG Gram laptop special features driver
  platform/x86: asus-wmi: Simplify the keyboard brightness updating process
  platform/x86: touchscreen_dmi: Add info for the Trekstor Primebook C11 convertible
  platform/x86: mlx-platform: Properly use mlxplat_mlxcpld_msn201x_items
  MAINTAINERS: intel_pmc_core: Update MAINTAINERS
  firmware: dcdbas: include linux/io.h
  platform/x86: intel-wmi-thunderbolt: Add dynamic debugging
  platform/x86: intel-wmi-thunderbolt: Convert to use SPDX identifier
  ...

50 files changed:
Documentation/ABI/testing/sysfs-platform-lg-laptop [new file with mode: 0644]
Documentation/laptops/lg-laptop.rst [new file with mode: 0644]
MAINTAINERS
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/dcdbas.c [deleted file]
drivers/firmware/dcdbas.h [deleted file]
drivers/firmware/dell_rbu.c [deleted file]
drivers/hid/Kconfig
drivers/hid/hid-asus.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acerhdf.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/dcdbas.c [new file with mode: 0644]
drivers/platform/x86/dcdbas.h [new file with mode: 0644]
drivers/platform/x86/dell-smbios-smm.c
drivers/platform/x86/dell_rbu.c [new file with mode: 0644]
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel-hid.c
drivers/platform/x86/intel-rst.c
drivers/platform/x86/intel-smartconnect.c
drivers/platform/x86/intel-wmi-thunderbolt.c
drivers/platform/x86/intel_atomisp2_pm.c [new file with mode: 0644]
drivers/platform/x86/intel_bxtwc_tmu.c
drivers/platform/x86/intel_cht_int33fe.c
drivers/platform/x86/intel_chtdc_ti_pwrbtn.c
drivers/platform/x86/intel_int0002_vgpio.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_ips.h
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/intel_mid_powerbtn.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/intel_oaktrail.c
drivers/platform/x86/intel_pmc_core.c
drivers/platform/x86/intel_pmc_core.h
drivers/platform/x86/intel_pmc_ipc.c
drivers/platform/x86/intel_punit_ipc.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/intel_scu_ipcutil.c
drivers/platform/x86/intel_telemetry_core.c
drivers/platform/x86/intel_telemetry_debugfs.c
drivers/platform/x86/intel_telemetry_pltdrv.c
drivers/platform/x86/intel_turbo_max_3.c
drivers/platform/x86/lg-laptop.c [new file with mode: 0644]
drivers/platform/x86/mlx-platform.c
drivers/platform/x86/touchscreen_dmi.c
drivers/platform/x86/wmi.c
include/linux/platform_data/x86/asus-wmi.h [new file with mode: 0644]
kernel/trace/trace_printk.c

diff --git a/Documentation/ABI/testing/sysfs-platform-lg-laptop b/Documentation/ABI/testing/sysfs-platform-lg-laptop
new file mode 100644 (file)
index 0000000..cf47749
--- /dev/null
@@ -0,0 +1,35 @@
+What:          /sys/devices/platform/lg-laptop/reader_mode
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Control reader mode. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/lg-laptop/fn_lock
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Control FN lock mode. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/lg-laptop/battery_care_limit
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Maximal battery charge level. Accepted values are 80 or 100.
+
+What:          /sys/devices/platform/lg-laptop/fan_mode
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Control fan mode. 1 for performance mode, 0 for silent mode.
+
+What:          /sys/devices/platform/lg-laptop/usb_charge
+Date:          October 2018
+KernelVersion: 4.20
+Contact:       "Matan Ziv-Av <matan@svgalib.org>
+Description:
+        Control USB port charging when device is turned off.
+        1 means on, 0 means off.
diff --git a/Documentation/laptops/lg-laptop.rst b/Documentation/laptops/lg-laptop.rst
new file mode 100644 (file)
index 0000000..e486fe7
--- /dev/null
@@ -0,0 +1,81 @@
+.. SPDX-License-Identifier: GPL-2.0+
+LG Gram laptop extra features
+=============================
+
+By Matan Ziv-Av <matan@svgalib.org>
+
+
+Hotkeys
+-------
+
+The following FN keys are ignored by the kernel without this driver:
+- FN-F1 (LG control panel)   - Generates F15
+- FN-F5 (Touchpad toggle)    - Generates F13
+- FN-F6 (Airplane mode)      - Generates RFKILL
+- FN-F8 (Keyboard backlight) - Generates F16.
+  This key also changes keyboard backlight mode.
+- FN-F9 (Reader mode)        - Generates F14
+
+The rest of the FN key work without a need for a special driver.
+
+
+Reader mode
+-----------
+
+Writing 0/1 to /sys/devices/platform/lg-laptop/reader_mode disables/enables
+reader mode. In this mode the screen colors change (blue color reduced),
+and the reader mode indicator LED (on F9 key) turns on.
+
+
+FN Lock
+-------
+
+Writing 0/1 to /sys/devices/platform/lg-laptop/fn_lock disables/enables
+FN lock.
+
+
+Battery care limit
+------------------
+
+Writing 80/100 to /sys/devices/platform/lg-laptop/battery_care_limit
+sets the maximum capacity to charge the battery. Limiting the charge
+reduces battery capacity loss over time.
+
+This value is reset to 100 when the kernel boots.
+
+
+Fan mode
+--------
+
+Writing 1/0 to /sys/devices/platform/lg-laptop/fan_mode disables/enables
+the fan silent mode.
+
+
+USB charge
+----------
+
+Writing 0/1 to /sys/devices/platform/lg-laptop/usb_charge disables/enables
+charging another device from the USB port while the device is turned off.
+
+This value is reset to 0 when the kernel boots.
+
+
+LEDs
+~~~~
+
+The are two LED devices supported by the driver:
+
+Keyboard backlight
+------------------
+
+A led device named kbd_led controls the keyboard backlight. There are three
+lighting level: off (0), low (127) and high (255).
+
+The keyboard backlight is also controlled by the key combination FN-F8
+which cycles through those levels.
+
+
+Touchpad indicator LED
+----------------------
+
+On the F5 key. Controlled by led device names tpad_led.
index 1c0f771b859ec24b6123efc7a511525613d86199..245ba32f53649a6897816da12439cd1cc4a5b737 100644 (file)
@@ -376,7 +376,7 @@ F:  drivers/platform/x86/i2c-multi-instantiate.c
 ACPI PMIC DRIVERS
 M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 M:     Len Brown <lenb@kernel.org>
-R:     Andy Shevchenko <andy@infradead.org>
+R:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 R:     Mika Westerberg <mika.westerberg@linux.intel.com>
 L:     linux-acpi@vger.kernel.org
 Q:     https://patchwork.kernel.org/project/linux-acpi/list/
@@ -4207,6 +4207,12 @@ M:       Pali Rohár <pali.rohar@gmail.com>
 S:     Maintained
 F:     drivers/platform/x86/dell-rbtn.*
 
+DELL REMOTE BIOS UPDATE DRIVER
+M:     Stuart Hayes <stuart.w.hayes@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/dell_rbu.c
+
 DELL LAPTOP SMM DRIVER
 M:     Pali Rohár <pali.rohar@gmail.com>
 S:     Maintained
@@ -4214,10 +4220,11 @@ F:      drivers/hwmon/dell-smm-hwmon.c
 F:     include/uapi/linux/i8k.h
 
 DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
-M:     Doug Warzecha <Douglas_Warzecha@dell.com>
+M:     Stuart Hayes <stuart.w.hayes@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     Documentation/dcdbas.txt
-F:     drivers/firmware/dcdbas.*
+F:     drivers/platform/x86/dcdbas.*
 
 DELL WMI NOTIFICATIONS DRIVER
 M:     Matthew Garrett <mjg59@srcf.ucam.org>
@@ -7347,6 +7354,12 @@ L:       alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     sound/soc/intel/
 
+INTEL ATOMISP2 DUMMY / POWER-MANAGEMENT DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/intel_atomisp2_pm.c
+
 INTEL C600 SERIES SAS CONTROLLER DRIVER
 M:     Intel SCU Linux support <intel-linux-scu@intel.com>
 M:     Artur Paszkiewicz <artur.paszkiewicz@intel.com>
@@ -7533,7 +7546,6 @@ M:        Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
 M:     Vishwanath Somayaji <vishwanath.somayaji@intel.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
-F:     arch/x86/include/asm/pmc_core.h
 F:     drivers/platform/x86/intel_pmc_core*
 
 INTEL PMC/P-Unit IPC DRIVER
@@ -7577,7 +7589,8 @@ F:        drivers/infiniband/hw/i40iw/
 F:     include/uapi/rdma/i40iw-abi.h
 
 INTEL TELEMETRY DRIVER
-M:     Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>
+M:     Rajneesh Bhardwaj <rajneesh.bhardwaj@linux.intel.com>
+M:     "David E. Box" <david.e.box@linux.intel.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     arch/x86/include/asm/intel_telemetry.h
@@ -8310,6 +8323,14 @@ W:       http://legousb.sourceforge.net/
 S:     Maintained
 F:     drivers/usb/misc/legousbtower.c
 
+LG LAPTOP EXTRAS
+M:     Matan Ziv-Av <matan@svgalib.org>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     Documentation/ABI/testing/sysfs-platform-lg-laptop
+F:     Documentation/laptops/lg-laptop.rst
+F:     drivers/platform/x86/lg-laptop.c
+
 LG2160 MEDIA DRIVER
 M:     Michael Krufky <mkrufky@linuxtv.org>
 L:     linux-media@vger.kernel.org
index 7670e8dda82951312feee7eca53f7499129c911a..7273e5082b4175be3601e28775506ce8b5ee89d9 100644 (file)
@@ -145,34 +145,6 @@ config EFI_PCDP
          See DIG64_HCDPv20_042804.pdf available from
          <http://www.dig64.org/specifications/> 
 
-config DELL_RBU
-       tristate "BIOS update support for DELL systems via sysfs"
-       depends on X86
-       select FW_LOADER
-       select FW_LOADER_USER_HELPER
-       help
-        Say m if you want to have the option of updating the BIOS for your
-        DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
-        supporting application to communicate with the BIOS regarding the new
-        image for the image update to take effect.
-        See <file:Documentation/dell_rbu.txt> for more details on the driver.
-
-config DCDBAS
-       tristate "Dell Systems Management Base Driver"
-       depends on X86
-       help
-         The Dell Systems Management Base Driver provides a sysfs interface
-         for systems management software to perform System Management
-         Interrupts (SMIs) and Host Control Actions (system power cycle or
-         power off after OS shutdown) on certain Dell systems.
-
-         See <file:Documentation/dcdbas.txt> for more details on the driver
-         and the Dell systems on which Dell systems management software makes
-         use of this driver.
-
-         Say Y or M here to enable the driver for use by Dell systems
-         management software such as Dell OpenManage.
-
 config DMIID
     bool "Export DMI identification via sysfs to userspace"
     depends on DMI
index 13660a9514379e7534af0f56c6e084f68b2ef02c..3158dffd9914e6afd44a51caf7acfd688c8984b3 100644 (file)
@@ -11,8 +11,6 @@ obj-$(CONFIG_DMI)             += dmi_scan.o
 obj-$(CONFIG_DMI_SYSFS)                += dmi-sysfs.o
 obj-$(CONFIG_EDD)              += edd.o
 obj-$(CONFIG_EFI_PCDP)         += pcdp.o
-obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
-obj-$(CONFIG_DCDBAS)           += dcdbas.o
 obj-$(CONFIG_DMIID)            += dmi-id.o
 obj-$(CONFIG_ISCSI_IBFT_FIND)  += iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)       += iscsi_ibft.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
deleted file mode 100644 (file)
index 0bdea60..0000000
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- *  dcdbas.c: Dell Systems Management Base Driver
- *
- *  The Dell Systems Management Base Driver provides a sysfs interface for
- *  systems management software to perform System Management Interrupts (SMIs)
- *  and Host Control Actions (power cycle or power off after OS shutdown) on
- *  Dell systems.
- *
- *  See Documentation/dcdbas.txt for more information.
- *
- *  Copyright (C) 1995-2006 Dell Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License v2.0 as published by
- *  the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/cpu.h>
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/mc146818rtc.h>
-#include <linux/module.h>
-#include <linux/reboot.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/mutex.h>
-#include <asm/io.h>
-
-#include "dcdbas.h"
-
-#define DRIVER_NAME            "dcdbas"
-#define DRIVER_VERSION         "5.6.0-3.2"
-#define DRIVER_DESCRIPTION     "Dell Systems Management Base Driver"
-
-static struct platform_device *dcdbas_pdev;
-
-static u8 *smi_data_buf;
-static dma_addr_t smi_data_buf_handle;
-static unsigned long smi_data_buf_size;
-static u32 smi_data_buf_phys_addr;
-static DEFINE_MUTEX(smi_data_lock);
-
-static unsigned int host_control_action;
-static unsigned int host_control_smi_type;
-static unsigned int host_control_on_shutdown;
-
-/**
- * smi_data_buf_free: free SMI data buffer
- */
-static void smi_data_buf_free(void)
-{
-       if (!smi_data_buf)
-               return;
-
-       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
-               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
-
-       dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
-                         smi_data_buf_handle);
-       smi_data_buf = NULL;
-       smi_data_buf_handle = 0;
-       smi_data_buf_phys_addr = 0;
-       smi_data_buf_size = 0;
-}
-
-/**
- * smi_data_buf_realloc: grow SMI data buffer if needed
- */
-static int smi_data_buf_realloc(unsigned long size)
-{
-       void *buf;
-       dma_addr_t handle;
-
-       if (smi_data_buf_size >= size)
-               return 0;
-
-       if (size > MAX_SMI_DATA_BUF_SIZE)
-               return -EINVAL;
-
-       /* new buffer is needed */
-       buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
-       if (!buf) {
-               dev_dbg(&dcdbas_pdev->dev,
-                       "%s: failed to allocate memory size %lu\n",
-                       __func__, size);
-               return -ENOMEM;
-       }
-       /* memory zeroed by dma_alloc_coherent */
-
-       if (smi_data_buf)
-               memcpy(buf, smi_data_buf, smi_data_buf_size);
-
-       /* free any existing buffer */
-       smi_data_buf_free();
-
-       /* set up new buffer for use */
-       smi_data_buf = buf;
-       smi_data_buf_handle = handle;
-       smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
-       smi_data_buf_size = size;
-
-       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
-               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
-
-       return 0;
-}
-
-static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
-                                          struct device_attribute *attr,
-                                          char *buf)
-{
-       return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
-}
-
-static ssize_t smi_data_buf_size_show(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "%lu\n", smi_data_buf_size);
-}
-
-static ssize_t smi_data_buf_size_store(struct device *dev,
-                                      struct device_attribute *attr,
-                                      const char *buf, size_t count)
-{
-       unsigned long buf_size;
-       ssize_t ret;
-
-       buf_size = simple_strtoul(buf, NULL, 10);
-
-       /* make sure SMI data buffer is at least buf_size */
-       mutex_lock(&smi_data_lock);
-       ret = smi_data_buf_realloc(buf_size);
-       mutex_unlock(&smi_data_lock);
-       if (ret)
-               return ret;
-
-       return count;
-}
-
-static ssize_t smi_data_read(struct file *filp, struct kobject *kobj,
-                            struct bin_attribute *bin_attr,
-                            char *buf, loff_t pos, size_t count)
-{
-       ssize_t ret;
-
-       mutex_lock(&smi_data_lock);
-       ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf,
-                                       smi_data_buf_size);
-       mutex_unlock(&smi_data_lock);
-       return ret;
-}
-
-static ssize_t smi_data_write(struct file *filp, struct kobject *kobj,
-                             struct bin_attribute *bin_attr,
-                             char *buf, loff_t pos, size_t count)
-{
-       ssize_t ret;
-
-       if ((pos + count) > MAX_SMI_DATA_BUF_SIZE)
-               return -EINVAL;
-
-       mutex_lock(&smi_data_lock);
-
-       ret = smi_data_buf_realloc(pos + count);
-       if (ret)
-               goto out;
-
-       memcpy(smi_data_buf + pos, buf, count);
-       ret = count;
-out:
-       mutex_unlock(&smi_data_lock);
-       return ret;
-}
-
-static ssize_t host_control_action_show(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
-{
-       return sprintf(buf, "%u\n", host_control_action);
-}
-
-static ssize_t host_control_action_store(struct device *dev,
-                                        struct device_attribute *attr,
-                                        const char *buf, size_t count)
-{
-       ssize_t ret;
-
-       /* make sure buffer is available for host control command */
-       mutex_lock(&smi_data_lock);
-       ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
-       mutex_unlock(&smi_data_lock);
-       if (ret)
-               return ret;
-
-       host_control_action = simple_strtoul(buf, NULL, 10);
-       return count;
-}
-
-static ssize_t host_control_smi_type_show(struct device *dev,
-                                         struct device_attribute *attr,
-                                         char *buf)
-{
-       return sprintf(buf, "%u\n", host_control_smi_type);
-}
-
-static ssize_t host_control_smi_type_store(struct device *dev,
-                                          struct device_attribute *attr,
-                                          const char *buf, size_t count)
-{
-       host_control_smi_type = simple_strtoul(buf, NULL, 10);
-       return count;
-}
-
-static ssize_t host_control_on_shutdown_show(struct device *dev,
-                                            struct device_attribute *attr,
-                                            char *buf)
-{
-       return sprintf(buf, "%u\n", host_control_on_shutdown);
-}
-
-static ssize_t host_control_on_shutdown_store(struct device *dev,
-                                             struct device_attribute *attr,
-                                             const char *buf, size_t count)
-{
-       host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
-       return count;
-}
-
-static int raise_smi(void *par)
-{
-       struct smi_cmd *smi_cmd = par;
-
-       if (smp_processor_id() != 0) {
-               dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
-                       __func__);
-               return -EBUSY;
-       }
-
-       /* generate SMI */
-       /* inb to force posted write through and make SMI happen now */
-       asm volatile (
-               "outb %b0,%w1\n"
-               "inb %w1"
-               : /* no output args */
-               : "a" (smi_cmd->command_code),
-                 "d" (smi_cmd->command_address),
-                 "b" (smi_cmd->ebx),
-                 "c" (smi_cmd->ecx)
-               : "memory"
-       );
-
-       return 0;
-}
-/**
- * dcdbas_smi_request: generate SMI request
- *
- * Called with smi_data_lock.
- */
-int dcdbas_smi_request(struct smi_cmd *smi_cmd)
-{
-       int ret;
-
-       if (smi_cmd->magic != SMI_CMD_MAGIC) {
-               dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
-                        __func__);
-               return -EBADR;
-       }
-
-       /* SMI requires CPU 0 */
-       get_online_cpus();
-       ret = smp_call_on_cpu(0, raise_smi, smi_cmd, true);
-       put_online_cpus();
-
-       return ret;
-}
-
-/**
- * smi_request_store:
- *
- * The valid values are:
- * 0: zero SMI data buffer
- * 1: generate calling interface SMI
- * 2: generate raw SMI
- *
- * User application writes smi_cmd to smi_data before telling driver
- * to generate SMI.
- */
-static ssize_t smi_request_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct smi_cmd *smi_cmd;
-       unsigned long val = simple_strtoul(buf, NULL, 10);
-       ssize_t ret;
-
-       mutex_lock(&smi_data_lock);
-
-       if (smi_data_buf_size < sizeof(struct smi_cmd)) {
-               ret = -ENODEV;
-               goto out;
-       }
-       smi_cmd = (struct smi_cmd *)smi_data_buf;
-
-       switch (val) {
-       case 2:
-               /* Raw SMI */
-               ret = dcdbas_smi_request(smi_cmd);
-               if (!ret)
-                       ret = count;
-               break;
-       case 1:
-               /* Calling Interface SMI */
-               smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
-               ret = dcdbas_smi_request(smi_cmd);
-               if (!ret)
-                       ret = count;
-               break;
-       case 0:
-               memset(smi_data_buf, 0, smi_data_buf_size);
-               ret = count;
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-out:
-       mutex_unlock(&smi_data_lock);
-       return ret;
-}
-EXPORT_SYMBOL(dcdbas_smi_request);
-
-/**
- * host_control_smi: generate host control SMI
- *
- * Caller must set up the host control command in smi_data_buf.
- */
-static int host_control_smi(void)
-{
-       struct apm_cmd *apm_cmd;
-       u8 *data;
-       unsigned long flags;
-       u32 num_ticks;
-       s8 cmd_status;
-       u8 index;
-
-       apm_cmd = (struct apm_cmd *)smi_data_buf;
-       apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
-
-       switch (host_control_smi_type) {
-       case HC_SMITYPE_TYPE1:
-               spin_lock_irqsave(&rtc_lock, flags);
-               /* write SMI data buffer physical address */
-               data = (u8 *)&smi_data_buf_phys_addr;
-               for (index = PE1300_CMOS_CMD_STRUCT_PTR;
-                    index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
-                    index++, data++) {
-                       outb(index,
-                            (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
-                       outb(*data,
-                            (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
-               }
-
-               /* first set status to -1 as called by spec */
-               cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
-               outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
-
-               /* generate SMM call */
-               outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
-               spin_unlock_irqrestore(&rtc_lock, flags);
-
-               /* wait a few to see if it executed */
-               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
-               while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
-                      == ESM_STATUS_CMD_UNSUCCESSFUL) {
-                       num_ticks--;
-                       if (num_ticks == EXPIRED_TIMER)
-                               return -ETIME;
-               }
-               break;
-
-       case HC_SMITYPE_TYPE2:
-       case HC_SMITYPE_TYPE3:
-               spin_lock_irqsave(&rtc_lock, flags);
-               /* write SMI data buffer physical address */
-               data = (u8 *)&smi_data_buf_phys_addr;
-               for (index = PE1400_CMOS_CMD_STRUCT_PTR;
-                    index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
-                    index++, data++) {
-                       outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
-                       outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
-               }
-
-               /* generate SMM call */
-               if (host_control_smi_type == HC_SMITYPE_TYPE3)
-                       outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
-               else
-                       outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
-
-               /* restore RTC index pointer since it was written to above */
-               CMOS_READ(RTC_REG_C);
-               spin_unlock_irqrestore(&rtc_lock, flags);
-
-               /* read control port back to serialize write */
-               cmd_status = inb(PE1400_APM_CONTROL_PORT);
-
-               /* wait a few to see if it executed */
-               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
-               while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
-                       num_ticks--;
-                       if (num_ticks == EXPIRED_TIMER)
-                               return -ETIME;
-               }
-               break;
-
-       default:
-               dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
-                       __func__, host_control_smi_type);
-               return -ENOSYS;
-       }
-
-       return 0;
-}
-
-/**
- * dcdbas_host_control: initiate host control
- *
- * This function is called by the driver after the system has
- * finished shutting down if the user application specified a
- * host control action to perform on shutdown.  It is safe to
- * use smi_data_buf at this point because the system has finished
- * shutting down and no userspace apps are running.
- */
-static void dcdbas_host_control(void)
-{
-       struct apm_cmd *apm_cmd;
-       u8 action;
-
-       if (host_control_action == HC_ACTION_NONE)
-               return;
-
-       action = host_control_action;
-       host_control_action = HC_ACTION_NONE;
-
-       if (!smi_data_buf) {
-               dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __func__);
-               return;
-       }
-
-       if (smi_data_buf_size < sizeof(struct apm_cmd)) {
-               dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
-                       __func__);
-               return;
-       }
-
-       apm_cmd = (struct apm_cmd *)smi_data_buf;
-
-       /* power off takes precedence */
-       if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
-               apm_cmd->command = ESM_APM_POWER_CYCLE;
-               apm_cmd->reserved = 0;
-               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0;
-               host_control_smi();
-       } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) {
-               apm_cmd->command = ESM_APM_POWER_CYCLE;
-               apm_cmd->reserved = 0;
-               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20;
-               host_control_smi();
-       }
-}
-
-/**
- * dcdbas_reboot_notify: handle reboot notification for host control
- */
-static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
-                               void *unused)
-{
-       switch (code) {
-       case SYS_DOWN:
-       case SYS_HALT:
-       case SYS_POWER_OFF:
-               if (host_control_on_shutdown) {
-                       /* firmware is going to perform host control action */
-                       printk(KERN_WARNING "Please wait for shutdown "
-                              "action to complete...\n");
-                       dcdbas_host_control();
-               }
-               break;
-       }
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block dcdbas_reboot_nb = {
-       .notifier_call = dcdbas_reboot_notify,
-       .next = NULL,
-       .priority = INT_MIN
-};
-
-static DCDBAS_BIN_ATTR_RW(smi_data);
-
-static struct bin_attribute *dcdbas_bin_attrs[] = {
-       &bin_attr_smi_data,
-       NULL
-};
-
-static DCDBAS_DEV_ATTR_RW(smi_data_buf_size);
-static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr);
-static DCDBAS_DEV_ATTR_WO(smi_request);
-static DCDBAS_DEV_ATTR_RW(host_control_action);
-static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
-static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
-
-static struct attribute *dcdbas_dev_attrs[] = {
-       &dev_attr_smi_data_buf_size.attr,
-       &dev_attr_smi_data_buf_phys_addr.attr,
-       &dev_attr_smi_request.attr,
-       &dev_attr_host_control_action.attr,
-       &dev_attr_host_control_smi_type.attr,
-       &dev_attr_host_control_on_shutdown.attr,
-       NULL
-};
-
-static const struct attribute_group dcdbas_attr_group = {
-       .attrs = dcdbas_dev_attrs,
-       .bin_attrs = dcdbas_bin_attrs,
-};
-
-static int dcdbas_probe(struct platform_device *dev)
-{
-       int error;
-
-       host_control_action = HC_ACTION_NONE;
-       host_control_smi_type = HC_SMITYPE_NONE;
-
-       dcdbas_pdev = dev;
-
-       /*
-        * BIOS SMI calls require buffer addresses be in 32-bit address space.
-        * This is done by setting the DMA mask below.
-        */
-       error = dma_set_coherent_mask(&dcdbas_pdev->dev, DMA_BIT_MASK(32));
-       if (error)
-               return error;
-
-       error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
-       if (error)
-               return error;
-
-       register_reboot_notifier(&dcdbas_reboot_nb);
-
-       dev_info(&dev->dev, "%s (version %s)\n",
-                DRIVER_DESCRIPTION, DRIVER_VERSION);
-
-       return 0;
-}
-
-static int dcdbas_remove(struct platform_device *dev)
-{
-       unregister_reboot_notifier(&dcdbas_reboot_nb);
-       sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
-
-       return 0;
-}
-
-static struct platform_driver dcdbas_driver = {
-       .driver         = {
-               .name   = DRIVER_NAME,
-       },
-       .probe          = dcdbas_probe,
-       .remove         = dcdbas_remove,
-};
-
-static const struct platform_device_info dcdbas_dev_info __initconst = {
-       .name           = DRIVER_NAME,
-       .id             = -1,
-       .dma_mask       = DMA_BIT_MASK(32),
-};
-
-static struct platform_device *dcdbas_pdev_reg;
-
-/**
- * dcdbas_init: initialize driver
- */
-static int __init dcdbas_init(void)
-{
-       int error;
-
-       error = platform_driver_register(&dcdbas_driver);
-       if (error)
-               return error;
-
-       dcdbas_pdev_reg = platform_device_register_full(&dcdbas_dev_info);
-       if (IS_ERR(dcdbas_pdev_reg)) {
-               error = PTR_ERR(dcdbas_pdev_reg);
-               goto err_unregister_driver;
-       }
-
-       return 0;
-
- err_unregister_driver:
-       platform_driver_unregister(&dcdbas_driver);
-       return error;
-}
-
-/**
- * dcdbas_exit: perform driver cleanup
- */
-static void __exit dcdbas_exit(void)
-{
-       /*
-        * make sure functions that use dcdbas_pdev are called
-        * before platform_device_unregister
-        */
-       unregister_reboot_notifier(&dcdbas_reboot_nb);
-
-       /*
-        * We have to free the buffer here instead of dcdbas_remove
-        * because only in module exit function we can be sure that
-        * all sysfs attributes belonging to this module have been
-        * released.
-        */
-       if (dcdbas_pdev)
-               smi_data_buf_free();
-       platform_device_unregister(dcdbas_pdev_reg);
-       platform_driver_unregister(&dcdbas_driver);
-}
-
-subsys_initcall_sync(dcdbas_init);
-module_exit(dcdbas_exit);
-
-MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_AUTHOR("Dell Inc.");
-MODULE_LICENSE("GPL");
-/* Any System or BIOS claiming to be by Dell */
-MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*");
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
deleted file mode 100644 (file)
index ca3cb0a..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *  dcdbas.h: Definitions for Dell Systems Management Base driver
- *
- *  Copyright (C) 1995-2005 Dell Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License v2.0 as published by
- *  the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- */
-
-#ifndef _DCDBAS_H_
-#define _DCDBAS_H_
-
-#include <linux/device.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
-#define MAX_SMI_DATA_BUF_SIZE                  (256 * 1024)
-
-#define HC_ACTION_NONE                         (0)
-#define HC_ACTION_HOST_CONTROL_POWEROFF                BIT(1)
-#define HC_ACTION_HOST_CONTROL_POWERCYCLE      BIT(2)
-
-#define HC_SMITYPE_NONE                                (0)
-#define HC_SMITYPE_TYPE1                       (1)
-#define HC_SMITYPE_TYPE2                       (2)
-#define HC_SMITYPE_TYPE3                       (3)
-
-#define ESM_APM_CMD                            (0x0A0)
-#define ESM_APM_POWER_CYCLE                    (0x10)
-#define ESM_STATUS_CMD_UNSUCCESSFUL            (-1)
-
-#define CMOS_BASE_PORT                         (0x070)
-#define CMOS_PAGE1_INDEX_PORT                  (0)
-#define CMOS_PAGE1_DATA_PORT                   (1)
-#define CMOS_PAGE2_INDEX_PORT_PIIX4            (2)
-#define CMOS_PAGE2_DATA_PORT_PIIX4             (3)
-#define PE1400_APM_CONTROL_PORT                        (0x0B0)
-#define PCAT_APM_CONTROL_PORT                  (0x0B2)
-#define PCAT_APM_STATUS_PORT                   (0x0B3)
-#define PE1300_CMOS_CMD_STRUCT_PTR             (0x38)
-#define PE1400_CMOS_CMD_STRUCT_PTR             (0x70)
-
-#define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN       (14)
-#define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM                (16)
-
-#define TIMEOUT_USEC_SHORT_SEMA_BLOCKING       (10000)
-#define EXPIRED_TIMER                          (0)
-
-#define SMI_CMD_MAGIC                          (0x534D4931)
-
-#define DCDBAS_DEV_ATTR_RW(_name) \
-       DEVICE_ATTR(_name,0600,_name##_show,_name##_store);
-
-#define DCDBAS_DEV_ATTR_RO(_name) \
-       DEVICE_ATTR(_name,0400,_name##_show,NULL);
-
-#define DCDBAS_DEV_ATTR_WO(_name) \
-       DEVICE_ATTR(_name,0200,NULL,_name##_store);
-
-#define DCDBAS_BIN_ATTR_RW(_name) \
-struct bin_attribute bin_attr_##_name = { \
-       .attr =  { .name = __stringify(_name), \
-                  .mode = 0600 }, \
-       .read =  _name##_read, \
-       .write = _name##_write, \
-}
-
-struct smi_cmd {
-       __u32 magic;
-       __u32 ebx;
-       __u32 ecx;
-       __u16 command_address;
-       __u8 command_code;
-       __u8 reserved;
-       __u8 command_buffer[1];
-} __attribute__ ((packed));
-
-struct apm_cmd {
-       __u8 command;
-       __s8 status;
-       __u16 reserved;
-       union {
-               struct {
-                       __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN];
-               } __attribute__ ((packed)) shortreq;
-
-               struct {
-                       __u16 num_sg_entries;
-                       struct {
-                               __u32 size;
-                               __u64 addr;
-                       } __attribute__ ((packed))
-                           sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM];
-               } __attribute__ ((packed)) longreq;
-       } __attribute__ ((packed)) parameters;
-} __attribute__ ((packed));
-
-int dcdbas_smi_request(struct smi_cmd *smi_cmd);
-
-#endif /* _DCDBAS_H_ */
-
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
deleted file mode 100644 (file)
index fb8af5c..0000000
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- * dell_rbu.c
- * Bios Update driver for Dell systems
- * Author: Dell Inc
- *         Abhay Salunke <abhay_salunke@dell.com>
- *
- * Copyright (C) 2005 Dell Inc.
- *
- * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
- * creating entries in the /sys file systems on Linux 2.6 and higher
- * kernels. The driver supports two mechanism to update the BIOS namely
- * contiguous and packetized. Both these methods still require having some
- * application to set the CMOS bit indicating the BIOS to update itself
- * after a reboot.
- *
- * Contiguous method:
- * This driver writes the incoming data in a monolithic image by allocating
- * contiguous physical pages large enough to accommodate the incoming BIOS
- * image size.
- *
- * Packetized method:
- * The driver writes the incoming packet image by allocating a new packet
- * on every time the packet data is written. This driver requires an
- * application to break the BIOS image in to fixed sized packet chunks.
- *
- * See Documentation/dell_rbu.txt for more info.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License v2.0 as published by
- * the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/blkdev.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/moduleparam.h>
-#include <linux/firmware.h>
-#include <linux/dma-mapping.h>
-
-MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
-MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("3.2");
-
-#define BIOS_SCAN_LIMIT 0xffffffff
-#define MAX_IMAGE_LENGTH 16
-static struct _rbu_data {
-       void *image_update_buffer;
-       unsigned long image_update_buffer_size;
-       unsigned long bios_image_size;
-       int image_update_ordernum;
-       int dma_alloc;
-       spinlock_t lock;
-       unsigned long packet_read_count;
-       unsigned long num_packets;
-       unsigned long packetsize;
-       unsigned long imagesize;
-       int entry_created;
-} rbu_data;
-
-static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
-module_param_string(image_type, image_type, sizeof (image_type), 0);
-MODULE_PARM_DESC(image_type,
-       "BIOS image type. choose- mono or packet or init");
-
-static unsigned long allocation_floor = 0x100000;
-module_param(allocation_floor, ulong, 0644);
-MODULE_PARM_DESC(allocation_floor,
-    "Minimum address for allocations when using Packet mode");
-
-struct packet_data {
-       struct list_head list;
-       size_t length;
-       void *data;
-       int ordernum;
-};
-
-static struct packet_data packet_data_head;
-
-static struct platform_device *rbu_device;
-static int context;
-static dma_addr_t dell_rbu_dmaaddr;
-
-static void init_packet_head(void)
-{
-       INIT_LIST_HEAD(&packet_data_head.list);
-       rbu_data.packet_read_count = 0;
-       rbu_data.num_packets = 0;
-       rbu_data.packetsize = 0;
-       rbu_data.imagesize = 0;
-}
-
-static int create_packet(void *data, size_t length)
-{
-       struct packet_data *newpacket;
-       int ordernum = 0;
-       int retval = 0;
-       unsigned int packet_array_size = 0;
-       void **invalid_addr_packet_array = NULL;
-       void *packet_data_temp_buf = NULL;
-       unsigned int idx = 0;
-
-       pr_debug("create_packet: entry \n");
-
-       if (!rbu_data.packetsize) {
-               pr_debug("create_packet: packetsize not specified\n");
-               retval = -EINVAL;
-               goto out_noalloc;
-       }
-
-       spin_unlock(&rbu_data.lock);
-
-       newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
-
-       if (!newpacket) {
-               printk(KERN_WARNING
-                       "dell_rbu:%s: failed to allocate new "
-                       "packet\n", __func__);
-               retval = -ENOMEM;
-               spin_lock(&rbu_data.lock);
-               goto out_noalloc;
-       }
-
-       ordernum = get_order(length);
-
-       /*
-        * BIOS errata mean we cannot allocate packets below 1MB or they will
-        * be overwritten by BIOS.
-        *
-        * array to temporarily hold packets
-        * that are below the allocation floor
-        *
-        * NOTE: very simplistic because we only need the floor to be at 1MB
-        *       due to BIOS errata. This shouldn't be used for higher floors
-        *       or you will run out of mem trying to allocate the array.
-        */
-       packet_array_size = max(
-                       (unsigned int)(allocation_floor / rbu_data.packetsize),
-                       (unsigned int)1);
-       invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *),
-                                               GFP_KERNEL);
-
-       if (!invalid_addr_packet_array) {
-               printk(KERN_WARNING
-                       "dell_rbu:%s: failed to allocate "
-                       "invalid_addr_packet_array \n",
-                       __func__);
-               retval = -ENOMEM;
-               spin_lock(&rbu_data.lock);
-               goto out_alloc_packet;
-       }
-
-       while (!packet_data_temp_buf) {
-               packet_data_temp_buf = (unsigned char *)
-                       __get_free_pages(GFP_KERNEL, ordernum);
-               if (!packet_data_temp_buf) {
-                       printk(KERN_WARNING
-                               "dell_rbu:%s: failed to allocate new "
-                               "packet\n", __func__);
-                       retval = -ENOMEM;
-                       spin_lock(&rbu_data.lock);
-                       goto out_alloc_packet_array;
-               }
-
-               if ((unsigned long)virt_to_phys(packet_data_temp_buf)
-                               < allocation_floor) {
-                       pr_debug("packet 0x%lx below floor at 0x%lx.\n",
-                                       (unsigned long)virt_to_phys(
-                                               packet_data_temp_buf),
-                                       allocation_floor);
-                       invalid_addr_packet_array[idx++] = packet_data_temp_buf;
-                       packet_data_temp_buf = NULL;
-               }
-       }
-       spin_lock(&rbu_data.lock);
-
-       newpacket->data = packet_data_temp_buf;
-
-       pr_debug("create_packet: newpacket at physical addr %lx\n",
-               (unsigned long)virt_to_phys(newpacket->data));
-
-       /* packets may not have fixed size */
-       newpacket->length = length;
-       newpacket->ordernum = ordernum;
-       ++rbu_data.num_packets;
-
-       /* initialize the newly created packet headers */
-       INIT_LIST_HEAD(&newpacket->list);
-       list_add_tail(&newpacket->list, &packet_data_head.list);
-
-       memcpy(newpacket->data, data, length);
-
-       pr_debug("create_packet: exit \n");
-
-out_alloc_packet_array:
-       /* always free packet array */
-       for (;idx>0;idx--) {
-               pr_debug("freeing unused packet below floor 0x%lx.\n",
-                       (unsigned long)virt_to_phys(
-                               invalid_addr_packet_array[idx-1]));
-               free_pages((unsigned long)invalid_addr_packet_array[idx-1],
-                       ordernum);
-       }
-       kfree(invalid_addr_packet_array);
-
-out_alloc_packet:
-       /* if error, free data */
-       if (retval)
-               kfree(newpacket);
-
-out_noalloc:
-       return retval;
-}
-
-static int packetize_data(const u8 *data, size_t length)
-{
-       int rc = 0;
-       int done = 0;
-       int packet_length;
-       u8 *temp;
-       u8 *end = (u8 *) data + length;
-       pr_debug("packetize_data: data length %zd\n", length);
-       if (!rbu_data.packetsize) {
-               printk(KERN_WARNING
-                       "dell_rbu: packetsize not specified\n");
-               return -EIO;
-       }
-
-       temp = (u8 *) data;
-
-       /* packetize the hunk */
-       while (!done) {
-               if ((temp + rbu_data.packetsize) < end)
-                       packet_length = rbu_data.packetsize;
-               else {
-                       /* this is the last packet */
-                       packet_length = end - temp;
-                       done = 1;
-               }
-
-               if ((rc = create_packet(temp, packet_length)))
-                       return rc;
-
-               pr_debug("%p:%td\n", temp, (end - temp));
-               temp += packet_length;
-       }
-
-       rbu_data.imagesize = length;
-
-       return rc;
-}
-
-static int do_packet_read(char *data, struct list_head *ptemp_list,
-       int length, int bytes_read, int *list_read_count)
-{
-       void *ptemp_buf;
-       struct packet_data *newpacket = NULL;
-       int bytes_copied = 0;
-       int j = 0;
-
-       newpacket = list_entry(ptemp_list, struct packet_data, list);
-       *list_read_count += newpacket->length;
-
-       if (*list_read_count > bytes_read) {
-               /* point to the start of unread data */
-               j = newpacket->length - (*list_read_count - bytes_read);
-               /* point to the offset in the packet buffer */
-               ptemp_buf = (u8 *) newpacket->data + j;
-               /*
-                * check if there is enough room in
-                * * the incoming buffer
-                */
-               if (length > (*list_read_count - bytes_read))
-                       /*
-                        * copy what ever is there in this
-                        * packet and move on
-                        */
-                       bytes_copied = (*list_read_count - bytes_read);
-               else
-                       /* copy the remaining */
-                       bytes_copied = length;
-               memcpy(data, ptemp_buf, bytes_copied);
-       }
-       return bytes_copied;
-}
-
-static int packet_read_list(char *data, size_t * pread_length)
-{
-       struct list_head *ptemp_list;
-       int temp_count = 0;
-       int bytes_copied = 0;
-       int bytes_read = 0;
-       int remaining_bytes = 0;
-       char *pdest = data;
-
-       /* check if we have any packets */
-       if (0 == rbu_data.num_packets)
-               return -ENOMEM;
-
-       remaining_bytes = *pread_length;
-       bytes_read = rbu_data.packet_read_count;
-
-       ptemp_list = (&packet_data_head.list)->next;
-       while (!list_empty(ptemp_list)) {
-               bytes_copied = do_packet_read(pdest, ptemp_list,
-                       remaining_bytes, bytes_read, &temp_count);
-               remaining_bytes -= bytes_copied;
-               bytes_read += bytes_copied;
-               pdest += bytes_copied;
-               /*
-                * check if we reached end of buffer before reaching the
-                * last packet
-                */
-               if (remaining_bytes == 0)
-                       break;
-
-               ptemp_list = ptemp_list->next;
-       }
-       /*finally set the bytes read */
-       *pread_length = bytes_read - rbu_data.packet_read_count;
-       rbu_data.packet_read_count = bytes_read;
-       return 0;
-}
-
-static void packet_empty_list(void)
-{
-       struct list_head *ptemp_list;
-       struct list_head *pnext_list;
-       struct packet_data *newpacket;
-
-       ptemp_list = (&packet_data_head.list)->next;
-       while (!list_empty(ptemp_list)) {
-               newpacket =
-                       list_entry(ptemp_list, struct packet_data, list);
-               pnext_list = ptemp_list->next;
-               list_del(ptemp_list);
-               ptemp_list = pnext_list;
-               /*
-                * zero out the RBU packet memory before freeing
-                * to make sure there are no stale RBU packets left in memory
-                */
-               memset(newpacket->data, 0, rbu_data.packetsize);
-               free_pages((unsigned long) newpacket->data,
-                       newpacket->ordernum);
-               kfree(newpacket);
-       }
-       rbu_data.packet_read_count = 0;
-       rbu_data.num_packets = 0;
-       rbu_data.imagesize = 0;
-}
-
-/*
- * img_update_free: Frees the buffer allocated for storing BIOS image
- * Always called with lock held and returned with lock held
- */
-static void img_update_free(void)
-{
-       if (!rbu_data.image_update_buffer)
-               return;
-       /*
-        * zero out this buffer before freeing it to get rid of any stale
-        * BIOS image copied in memory.
-        */
-       memset(rbu_data.image_update_buffer, 0,
-               rbu_data.image_update_buffer_size);
-       if (rbu_data.dma_alloc == 1)
-               dma_free_coherent(NULL, rbu_data.bios_image_size,
-                       rbu_data.image_update_buffer, dell_rbu_dmaaddr);
-       else
-               free_pages((unsigned long) rbu_data.image_update_buffer,
-                       rbu_data.image_update_ordernum);
-
-       /*
-        * Re-initialize the rbu_data variables after a free
-        */
-       rbu_data.image_update_ordernum = -1;
-       rbu_data.image_update_buffer = NULL;
-       rbu_data.image_update_buffer_size = 0;
-       rbu_data.bios_image_size = 0;
-       rbu_data.dma_alloc = 0;
-}
-
-/*
- * img_update_realloc: This function allocates the contiguous pages to
- * accommodate the requested size of data. The memory address and size
- * values are stored globally and on every call to this function the new
- * size is checked to see if more data is required than the existing size.
- * If true the previous memory is freed and new allocation is done to
- * accommodate the new size. If the incoming size is less then than the
- * already allocated size, then that memory is reused. This function is
- * called with lock held and returns with lock held.
- */
-static int img_update_realloc(unsigned long size)
-{
-       unsigned char *image_update_buffer = NULL;
-       unsigned long rc;
-       unsigned long img_buf_phys_addr;
-       int ordernum;
-       int dma_alloc = 0;
-
-       /*
-        * check if the buffer of sufficient size has been
-        * already allocated
-        */
-       if (rbu_data.image_update_buffer_size >= size) {
-               /*
-                * check for corruption
-                */
-               if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
-                       printk(KERN_ERR "dell_rbu:%s: corruption "
-                               "check failed\n", __func__);
-                       return -EINVAL;
-               }
-               /*
-                * we have a valid pre-allocated buffer with
-                * sufficient size
-                */
-               return 0;
-       }
-
-       /*
-        * free any previously allocated buffer
-        */
-       img_update_free();
-
-       spin_unlock(&rbu_data.lock);
-
-       ordernum = get_order(size);
-       image_update_buffer =
-               (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
-
-       img_buf_phys_addr =
-               (unsigned long) virt_to_phys(image_update_buffer);
-
-       if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
-               free_pages((unsigned long) image_update_buffer, ordernum);
-               ordernum = -1;
-               image_update_buffer = dma_alloc_coherent(NULL, size,
-                       &dell_rbu_dmaaddr, GFP_KERNEL);
-               dma_alloc = 1;
-       }
-
-       spin_lock(&rbu_data.lock);
-
-       if (image_update_buffer != NULL) {
-               rbu_data.image_update_buffer = image_update_buffer;
-               rbu_data.image_update_buffer_size = size;
-               rbu_data.bios_image_size =
-                       rbu_data.image_update_buffer_size;
-               rbu_data.image_update_ordernum = ordernum;
-               rbu_data.dma_alloc = dma_alloc;
-               rc = 0;
-       } else {
-               pr_debug("Not enough memory for image update:"
-                       "size = %ld\n", size);
-               rc = -ENOMEM;
-       }
-
-       return rc;
-}
-
-static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
-{
-       int retval;
-       size_t bytes_left;
-       size_t data_length;
-       char *ptempBuf = buffer;
-
-       /* check to see if we have something to return */
-       if (rbu_data.num_packets == 0) {
-               pr_debug("read_packet_data: no packets written\n");
-               retval = -ENOMEM;
-               goto read_rbu_data_exit;
-       }
-
-       if (pos > rbu_data.imagesize) {
-               retval = 0;
-               printk(KERN_WARNING "dell_rbu:read_packet_data: "
-                       "data underrun\n");
-               goto read_rbu_data_exit;
-       }
-
-       bytes_left = rbu_data.imagesize - pos;
-       data_length = min(bytes_left, count);
-
-       if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
-               goto read_rbu_data_exit;
-
-       if ((pos + count) > rbu_data.imagesize) {
-               rbu_data.packet_read_count = 0;
-               /* this was the last copy */
-               retval = bytes_left;
-       } else
-               retval = count;
-
-      read_rbu_data_exit:
-       return retval;
-}
-
-static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
-{
-       /* check to see if we have something to return */
-       if ((rbu_data.image_update_buffer == NULL) ||
-               (rbu_data.bios_image_size == 0)) {
-               pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
-                       "bios_image_size %lu\n",
-                       rbu_data.image_update_buffer,
-                       rbu_data.bios_image_size);
-               return -ENOMEM;
-       }
-
-       return memory_read_from_buffer(buffer, count, &pos,
-                       rbu_data.image_update_buffer, rbu_data.bios_image_size);
-}
-
-static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj,
-                            struct bin_attribute *bin_attr,
-                            char *buffer, loff_t pos, size_t count)
-{
-       ssize_t ret_count = 0;
-
-       spin_lock(&rbu_data.lock);
-
-       if (!strcmp(image_type, "mono"))
-               ret_count = read_rbu_mono_data(buffer, pos, count);
-       else if (!strcmp(image_type, "packet"))
-               ret_count = read_packet_data(buffer, pos, count);
-       else
-               pr_debug("read_rbu_data: invalid image type specified\n");
-
-       spin_unlock(&rbu_data.lock);
-       return ret_count;
-}
-
-static void callbackfn_rbu(const struct firmware *fw, void *context)
-{
-       rbu_data.entry_created = 0;
-
-       if (!fw)
-               return;
-
-       if (!fw->size)
-               goto out;
-
-       spin_lock(&rbu_data.lock);
-       if (!strcmp(image_type, "mono")) {
-               if (!img_update_realloc(fw->size))
-                       memcpy(rbu_data.image_update_buffer,
-                               fw->data, fw->size);
-       } else if (!strcmp(image_type, "packet")) {
-               /*
-                * we need to free previous packets if a
-                * new hunk of packets needs to be downloaded
-                */
-               packet_empty_list();
-               if (packetize_data(fw->data, fw->size))
-                       /* Incase something goes wrong when we are
-                        * in middle of packetizing the data, we
-                        * need to free up whatever packets might
-                        * have been created before we quit.
-                        */
-                       packet_empty_list();
-       } else
-               pr_debug("invalid image type specified.\n");
-       spin_unlock(&rbu_data.lock);
- out:
-       release_firmware(fw);
-}
-
-static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj,
-                                  struct bin_attribute *bin_attr,
-                                  char *buffer, loff_t pos, size_t count)
-{
-       int size = 0;
-       if (!pos)
-               size = scnprintf(buffer, count, "%s\n", image_type);
-       return size;
-}
-
-static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj,
-                                   struct bin_attribute *bin_attr,
-                                   char *buffer, loff_t pos, size_t count)
-{
-       int rc = count;
-       int req_firm_rc = 0;
-       int i;
-       spin_lock(&rbu_data.lock);
-       /*
-        * Find the first newline or space
-        */
-       for (i = 0; i < count; ++i)
-               if (buffer[i] == '\n' || buffer[i] == ' ') {
-                       buffer[i] = '\0';
-                       break;
-               }
-       if (i == count)
-               buffer[count] = '\0';
-
-       if (strstr(buffer, "mono"))
-               strcpy(image_type, "mono");
-       else if (strstr(buffer, "packet"))
-               strcpy(image_type, "packet");
-       else if (strstr(buffer, "init")) {
-               /*
-                * If due to the user error the driver gets in a bad
-                * state where even though it is loaded , the
-                * /sys/class/firmware/dell_rbu entries are missing.
-                * to cover this situation the user can recreate entries
-                * by writing init to image_type.
-                */
-               if (!rbu_data.entry_created) {
-                       spin_unlock(&rbu_data.lock);
-                       req_firm_rc = request_firmware_nowait(THIS_MODULE,
-                               FW_ACTION_NOHOTPLUG, "dell_rbu",
-                               &rbu_device->dev, GFP_KERNEL, &context,
-                               callbackfn_rbu);
-                       if (req_firm_rc) {
-                               printk(KERN_ERR
-                                       "dell_rbu:%s request_firmware_nowait"
-                                       " failed %d\n", __func__, rc);
-                               rc = -EIO;
-                       } else
-                               rbu_data.entry_created = 1;
-
-                       spin_lock(&rbu_data.lock);
-               }
-       } else {
-               printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
-               spin_unlock(&rbu_data.lock);
-               return -EINVAL;
-       }
-
-       /* we must free all previous allocations */
-       packet_empty_list();
-       img_update_free();
-       spin_unlock(&rbu_data.lock);
-
-       return rc;
-}
-
-static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj,
-                                   struct bin_attribute *bin_attr,
-                                   char *buffer, loff_t pos, size_t count)
-{
-       int size = 0;
-       if (!pos) {
-               spin_lock(&rbu_data.lock);
-               size = scnprintf(buffer, count, "%lu\n", rbu_data.packetsize);
-               spin_unlock(&rbu_data.lock);
-       }
-       return size;
-}
-
-static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj,
-                                    struct bin_attribute *bin_attr,
-                                    char *buffer, loff_t pos, size_t count)
-{
-       unsigned long temp;
-       spin_lock(&rbu_data.lock);
-       packet_empty_list();
-       sscanf(buffer, "%lu", &temp);
-       if (temp < 0xffffffff)
-               rbu_data.packetsize = temp;
-
-       spin_unlock(&rbu_data.lock);
-       return count;
-}
-
-static struct bin_attribute rbu_data_attr = {
-       .attr = {.name = "data", .mode = 0444},
-       .read = read_rbu_data,
-};
-
-static struct bin_attribute rbu_image_type_attr = {
-       .attr = {.name = "image_type", .mode = 0644},
-       .read = read_rbu_image_type,
-       .write = write_rbu_image_type,
-};
-
-static struct bin_attribute rbu_packet_size_attr = {
-       .attr = {.name = "packet_size", .mode = 0644},
-       .read = read_rbu_packet_size,
-       .write = write_rbu_packet_size,
-};
-
-static int __init dcdrbu_init(void)
-{
-       int rc;
-       spin_lock_init(&rbu_data.lock);
-
-       init_packet_head();
-       rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0);
-       if (IS_ERR(rbu_device)) {
-               printk(KERN_ERR
-                       "dell_rbu:%s:platform_device_register_simple "
-                       "failed\n", __func__);
-               return PTR_ERR(rbu_device);
-       }
-
-       rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
-       if (rc)
-               goto out_devreg;
-       rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
-       if (rc)
-               goto out_data;
-       rc = sysfs_create_bin_file(&rbu_device->dev.kobj,
-               &rbu_packet_size_attr);
-       if (rc)
-               goto out_imtype;
-
-       rbu_data.entry_created = 0;
-       return 0;
-
-out_imtype:
-       sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
-out_data:
-       sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
-out_devreg:
-       platform_device_unregister(rbu_device);
-       return rc;
-}
-
-static __exit void dcdrbu_exit(void)
-{
-       spin_lock(&rbu_data.lock);
-       packet_empty_list();
-       img_update_free();
-       spin_unlock(&rbu_data.lock);
-       platform_device_unregister(rbu_device);
-}
-
-module_exit(dcdrbu_exit);
-module_init(dcdrbu_init);
-
-/* vim:noet:ts=8:sw=8
-*/
index 5ed319e3b084d920cddf6adc5a665c5732c8c77c..41e9935fc5849e0992e3103912fbe01a5af2a555 100644 (file)
@@ -149,6 +149,7 @@ config HID_APPLEIR
 config HID_ASUS
        tristate "Asus"
        depends on LEDS_CLASS
+       depends on ASUS_WMI || ASUS_WMI=n
        ---help---
        Support for Asus notebook built-in keyboard and touchpad via i2c, and
        the Asus Republic of Gamers laptop keyboard special keys.
index 88a5672f42cd814187ede87e8783414023824bf2..dc6d6477e9611eb2ba93a8d687bfaf9d4e634ef8 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/dmi.h>
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/platform_data/x86/asus-wmi.h>
 #include <linux/input/mt.h>
 #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
 
@@ -349,6 +350,24 @@ static void asus_kbd_backlight_work(struct work_struct *work)
                hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret);
 }
 
+/* WMI-based keyboard backlight LED control (via asus-wmi driver) takes
+ * precedence. We only activate HID-based backlight control when the
+ * WMI control is not available.
+ */
+static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev)
+{
+       u32 value;
+       int ret;
+
+       ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2,
+                                      ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value);
+       hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value);
+       if (ret)
+               return false;
+
+       return !!(value & ASUS_WMI_DSTS_PRESENCE_BIT);
+}
+
 static int asus_kbd_register_leds(struct hid_device *hdev)
 {
        struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
@@ -436,7 +455,9 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
 
        drvdata->input = input;
 
-       if (drvdata->enable_backlight && asus_kbd_register_leds(hdev))
+       if (drvdata->enable_backlight &&
+           !asus_kbd_wmi_led_control_present(hdev) &&
+           asus_kbd_register_leds(hdev))
                hid_warn(hdev, "Failed to initialize backlight.\n");
 
        return 0;
index bdac939de223c9242385bfd77c23a343258fc687..54f6a40c75c69c667ac3d4591dde89fd99bac3be 100644 (file)
@@ -60,7 +60,10 @@ config ACERHDF
 
          After loading this driver the BIOS is still in control of the fan.
          To let the kernel handle the fan, do:
-         echo -n enabled > /sys/class/thermal/thermal_zone0/mode
+         echo -n enabled > /sys/class/thermal/thermal_zoneN/mode
+         where N=0,1,2... depending on the number of thermal nodes and the
+         detection order of your particular system.  The "type" parameter
+         in the same node directory will tell you if it is "acerhdf".
 
          For more information about this driver see
          <http://piie.net/files/acerhdf_README.txt>
@@ -105,6 +108,22 @@ config ASUS_LAPTOP
 
          If you have an ACPI-compatible ASUS laptop, say Y or M here.
 
+config DCDBAS
+       tristate "Dell Systems Management Base Driver"
+       depends on X86
+       help
+         The Dell Systems Management Base Driver provides a sysfs interface
+         for systems management software to perform System Management
+         Interrupts (SMIs) and Host Control Actions (system power cycle or
+         power off after OS shutdown) on certain Dell systems.
+
+         See <file:Documentation/dcdbas.txt> for more details on the driver
+         and the Dell systems on which Dell systems management software makes
+         use of this driver.
+
+         Say Y or M here to enable the driver for use by Dell systems
+         management software such as Dell OpenManage.
+
 #
 # The DELL_SMBIOS driver depends on ACPI_WMI and/or DCDBAS if those
 # backends are selected. The "depends" line prevents a configuration
@@ -227,6 +246,18 @@ config DELL_RBTN
          To compile this driver as a module, choose M here: the module will
          be called dell-rbtn.
 
+config DELL_RBU
+       tristate "BIOS update support for DELL systems via sysfs"
+       depends on X86
+       select FW_LOADER
+       select FW_LOADER_USER_HELPER
+       help
+        Say m if you want to have the option of updating the BIOS for your
+        DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
+        supporting application to communicate with the BIOS regarding the new
+        image for the image update to take effect.
+        See <file:Documentation/dell_rbu.txt> for more details on the driver.
+
 
 config FUJITSU_LAPTOP
        tristate "Fujitsu Laptop Extras"
@@ -336,6 +367,20 @@ config HP_WMI
         To compile this driver as a module, choose M here: the module will
         be called hp-wmi.
 
+config LG_LAPTOP
+       tristate "LG Laptop Extras"
+       depends on ACPI
+       depends on ACPI_WMI
+       depends on INPUT
+       select INPUT_SPARSEKMAP
+       select LEDS_CLASS
+       help
+        This driver adds support for hotkeys as well as control of keyboard
+        backlight, battery maximum charge level and various other ACPI
+        features.
+
+        If you have an LG Gram laptop, say Y or M here.
+
 config MSI_LAPTOP
        tristate "MSI Laptop Extras"
        depends on ACPI
@@ -1231,6 +1276,18 @@ config I2C_MULTI_INSTANTIATE
          To compile this driver as a module, choose M here: the module
          will be called i2c-multi-instantiate.
 
+config INTEL_ATOMISP2_PM
+       tristate "Intel AtomISP2 dummy / power-management driver"
+       depends on PCI && IOSF_MBI && PM
+       help
+         Power-management driver for Intel's Image Signal Processor found on
+         Bay and Cherry Trail devices. This dummy driver's sole purpose is to
+         turn the ISP off (put it in D3) to save power and to allow entering
+         of S0ix modes.
+
+         To compile this driver as a module, choose M here: the module
+         will be called intel_atomisp2_pm.
+
 endif # X86_PLATFORM_DEVICES
 
 config PMC_ATOM
index e6d1becf81ce8c6bd526e196b8c167576d0f5c6f..39ae94135406b69bb7cef9bcb8d24242382afe35 100644 (file)
@@ -9,9 +9,11 @@ obj-$(CONFIG_ASUS_NB_WMI)      += asus-nb-wmi.o
 obj-$(CONFIG_ASUS_WIRELESS)    += asus-wireless.o
 obj-$(CONFIG_EEEPC_LAPTOP)     += eeepc-laptop.o
 obj-$(CONFIG_EEEPC_WMI)                += eeepc-wmi.o
+obj-$(CONFIG_LG_LAPTOP)                += lg-laptop.o
 obj-$(CONFIG_MSI_LAPTOP)       += msi-laptop.o
 obj-$(CONFIG_ACPI_CMPC)                += classmate-laptop.o
 obj-$(CONFIG_COMPAL_LAPTOP)    += compal-laptop.o
+obj-$(CONFIG_DCDBAS)           += dcdbas.o
 obj-$(CONFIG_DELL_SMBIOS)      += dell-smbios.o
 dell-smbios-objs               := dell-smbios-base.o
 dell-smbios-$(CONFIG_DELL_SMBIOS_WMI)  += dell-smbios-wmi.o
@@ -23,6 +25,7 @@ obj-$(CONFIG_DELL_WMI_AIO)    += dell-wmi-aio.o
 obj-$(CONFIG_DELL_WMI_LED)     += dell-wmi-led.o
 obj-$(CONFIG_DELL_SMO8800)     += dell-smo8800.o
 obj-$(CONFIG_DELL_RBTN)                += dell-rbtn.o
+obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
 obj-$(CONFIG_ACER_WMI)         += acer-wmi.o
 obj-$(CONFIG_ACER_WIRELESS)    += acer-wireless.o
 obj-$(CONFIG_ACERHDF)          += acerhdf.o
@@ -92,3 +95,4 @@ obj-$(CONFIG_MLX_PLATFORM)    += mlx-platform.o
 obj-$(CONFIG_INTEL_TURBO_MAX_3) += intel_turbo_max_3.o
 obj-$(CONFIG_INTEL_CHTDC_TI_PWRBTN)    += intel_chtdc_ti_pwrbtn.o
 obj-$(CONFIG_I2C_MULTI_INSTANTIATE)    += i2c-multi-instantiate.o
+obj-$(CONFIG_INTEL_ATOMISP2_PM)        += intel_atomisp2_pm.o
index ea22591ee66feb9c08d8a831cbb822d8b9ab7591..50522422537886c26c849af01b18694be049387b 100644 (file)
@@ -86,6 +86,7 @@ static unsigned int interval = 10;
 static unsigned int fanon = 60000;
 static unsigned int fanoff = 53000;
 static unsigned int verbose;
+static unsigned int list_supported;
 static unsigned int fanstate = ACERHDF_FAN_AUTO;
 static char force_bios[16];
 static char force_product[16];
@@ -104,10 +105,12 @@ module_param(fanoff, uint, 0600);
 MODULE_PARM_DESC(fanoff, "Turn the fan off below this temperature");
 module_param(verbose, uint, 0600);
 MODULE_PARM_DESC(verbose, "Enable verbose dmesg output");
+module_param(list_supported, uint, 0600);
+MODULE_PARM_DESC(list_supported, "List supported models and BIOS versions");
 module_param_string(force_bios, force_bios, 16, 0);
-MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check");
+MODULE_PARM_DESC(force_bios, "Pretend system has this known supported BIOS version");
 module_param_string(force_product, force_product, 16, 0);
-MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check");
+MODULE_PARM_DESC(force_product, "Pretend system is this known supported model");
 
 /*
  * cmd_off: to switch the fan completely off and check if the fan is off
@@ -130,7 +133,7 @@ static const struct manualcmd mcmd = {
        .moff = 0xff,
 };
 
-/* BIOS settings */
+/* BIOS settings - only used during probe */
 struct bios_settings {
        const char *vendor;
        const char *product;
@@ -141,8 +144,18 @@ struct bios_settings {
        int mcmd_enable;
 };
 
+/* This could be a daughter struct in the above, but not worth the redirect */
+struct ctrl_settings {
+       u8 fanreg;
+       u8 tempreg;
+       struct fancmd cmd;
+       int mcmd_enable;
+};
+
+static struct ctrl_settings ctrl_cfg __read_mostly;
+
 /* Register addresses and values for different BIOS versions */
-static const struct bios_settings bios_tbl[] = {
+static const struct bios_settings bios_tbl[] __initconst = {
        /* AOA110 */
        {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00}, 0},
        {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00}, 0},
@@ -233,6 +246,7 @@ static const struct bios_settings bios_tbl[] = {
        {"Gateway", "LT31",   "v1.3201",  0x55, 0x58, {0x9e, 0x00}, 0},
        {"Gateway", "LT31",   "v1.3302",  0x55, 0x58, {0x9e, 0x00}, 0},
        {"Gateway", "LT31",   "v1.3303t", 0x55, 0x58, {0x9e, 0x00}, 0},
+       {"Gateway", "LT31",   "v1.3307",  0x55, 0x58, {0x9e, 0x00}, 0},
        /* Packard Bell */
        {"Packard Bell", "DOA150",  "v0.3104",  0x55, 0x58, {0x21, 0x00}, 0},
        {"Packard Bell", "DOA150",  "v0.3105",  0x55, 0x58, {0x20, 0x00}, 0},
@@ -256,8 +270,6 @@ static const struct bios_settings bios_tbl[] = {
        {"", "", "", 0, 0, {0, 0}, 0}
 };
 
-static const struct bios_settings *bios_cfg __read_mostly;
-
 /*
  * this struct is used to instruct thermal layer to use bang_bang instead of
  * default governor for acerhdf
@@ -270,7 +282,7 @@ static int acerhdf_get_temp(int *temp)
 {
        u8 read_temp;
 
-       if (ec_read(bios_cfg->tempreg, &read_temp))
+       if (ec_read(ctrl_cfg.tempreg, &read_temp))
                return -EINVAL;
 
        *temp = read_temp * 1000;
@@ -282,10 +294,10 @@ static int acerhdf_get_fanstate(int *state)
 {
        u8 fan;
 
-       if (ec_read(bios_cfg->fanreg, &fan))
+       if (ec_read(ctrl_cfg.fanreg, &fan))
                return -EINVAL;
 
-       if (fan != bios_cfg->cmd.cmd_off)
+       if (fan != ctrl_cfg.cmd.cmd_off)
                *state = ACERHDF_FAN_AUTO;
        else
                *state = ACERHDF_FAN_OFF;
@@ -306,13 +318,13 @@ static void acerhdf_change_fanstate(int state)
                state = ACERHDF_FAN_AUTO;
        }
 
-       cmd = (state == ACERHDF_FAN_OFF) ? bios_cfg->cmd.cmd_off
-                                        : bios_cfg->cmd.cmd_auto;
+       cmd = (state == ACERHDF_FAN_OFF) ? ctrl_cfg.cmd.cmd_off
+                                        : ctrl_cfg.cmd.cmd_auto;
        fanstate = state;
 
-       ec_write(bios_cfg->fanreg, cmd);
+       ec_write(ctrl_cfg.fanreg, cmd);
 
-       if (bios_cfg->mcmd_enable && state == ACERHDF_FAN_OFF) {
+       if (ctrl_cfg.mcmd_enable && state == ACERHDF_FAN_OFF) {
                if (verbose)
                        pr_notice("turning off fan manually\n");
                ec_write(mcmd.mreg, mcmd.moff);
@@ -615,10 +627,11 @@ static int str_starts_with(const char *str, const char *start)
 }
 
 /* check hardware */
-static int acerhdf_check_hardware(void)
+static int __init acerhdf_check_hardware(void)
 {
        char const *vendor, *version, *product;
        const struct bios_settings *bt = NULL;
+       int found = 0;
 
        /* get BIOS data */
        vendor  = dmi_get_system_info(DMI_SYS_VENDOR);
@@ -632,6 +645,17 @@ static int acerhdf_check_hardware(void)
 
        pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER);
 
+       if (list_supported) {
+               pr_info("List of supported Manufacturer/Model/BIOS:\n");
+               pr_info("---------------------------------------------------\n");
+               for (bt = bios_tbl; bt->vendor[0]; bt++) {
+                       pr_info("%-13s | %-17s | %-10s\n", bt->vendor,
+                               bt->product, bt->version);
+               }
+               pr_info("---------------------------------------------------\n");
+               return -ECANCELED;
+       }
+
        if (force_bios[0]) {
                version = force_bios;
                pr_info("forcing BIOS version: %s\n", version);
@@ -657,30 +681,36 @@ static int acerhdf_check_hardware(void)
                if (str_starts_with(vendor, bt->vendor) &&
                                str_starts_with(product, bt->product) &&
                                str_starts_with(version, bt->version)) {
-                       bios_cfg = bt;
+                       found = 1;
                        break;
                }
        }
 
-       if (!bios_cfg) {
+       if (!found) {
                pr_err("unknown (unsupported) BIOS version %s/%s/%s, please report, aborting!\n",
                       vendor, product, version);
                return -EINVAL;
        }
 
+       /* Copy control settings from BIOS table before we free it. */
+       ctrl_cfg.fanreg = bt->fanreg;
+       ctrl_cfg.tempreg = bt->tempreg;
+       memcpy(&ctrl_cfg.cmd, &bt->cmd, sizeof(struct fancmd));
+       ctrl_cfg.mcmd_enable = bt->mcmd_enable;
+
        /*
         * if started with kernel mode off, prevent the kernel from switching
         * off the fan
         */
        if (!kernelmode) {
                pr_notice("Fan control off, to enable do:\n");
-               pr_notice("echo -n \"enabled\" > /sys/class/thermal/thermal_zone0/mode\n");
+               pr_notice("echo -n \"enabled\" > /sys/class/thermal/thermal_zoneN/mode # N=0,1,2...\n");
        }
 
        return 0;
 }
 
-static int acerhdf_register_platform(void)
+static int __init acerhdf_register_platform(void)
 {
        int err = 0;
 
@@ -712,7 +742,7 @@ static void acerhdf_unregister_platform(void)
        platform_driver_unregister(&acerhdf_driver);
 }
 
-static int acerhdf_register_thermal(void)
+static int __init acerhdf_register_thermal(void)
 {
        cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL,
                                                 &acerhdf_cooling_ops);
index 93ee2d5466f8092978f57bf74ca84ee9c3cc1cc8..c285a16675ee7d912280028bf5f94c552fad6371 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/platform_data/x86/asus-wmi.h>
 #include <linux/platform_device.h>
 #include <linux/thermal.h>
 #include <linux/acpi.h>
@@ -69,89 +70,6 @@ MODULE_LICENSE("GPL");
 #define NOTIFY_KBD_BRTDWN              0xc5
 #define NOTIFY_KBD_BRTTOGGLE           0xc7
 
-/* WMI Methods */
-#define ASUS_WMI_METHODID_SPEC         0x43455053 /* BIOS SPECification */
-#define ASUS_WMI_METHODID_SFBD         0x44424653 /* Set First Boot Device */
-#define ASUS_WMI_METHODID_GLCD         0x44434C47 /* Get LCD status */
-#define ASUS_WMI_METHODID_GPID         0x44495047 /* Get Panel ID?? (Resol) */
-#define ASUS_WMI_METHODID_QMOD         0x444F4D51 /* Quiet MODe */
-#define ASUS_WMI_METHODID_SPLV         0x4C425053 /* Set Panel Light Value */
-#define ASUS_WMI_METHODID_AGFN         0x4E464741 /* FaN? */
-#define ASUS_WMI_METHODID_SFUN         0x4E554653 /* FUNCtionalities */
-#define ASUS_WMI_METHODID_SDSP         0x50534453 /* Set DiSPlay output */
-#define ASUS_WMI_METHODID_GDSP         0x50534447 /* Get DiSPlay output */
-#define ASUS_WMI_METHODID_DEVP         0x50564544 /* DEVice Policy */
-#define ASUS_WMI_METHODID_OSVR         0x5256534F /* OS VeRsion */
-#define ASUS_WMI_METHODID_DSTS         0x53544344 /* Device STatuS */
-#define ASUS_WMI_METHODID_DSTS2                0x53545344 /* Device STatuS #2*/
-#define ASUS_WMI_METHODID_BSTS         0x53545342 /* Bios STatuS ? */
-#define ASUS_WMI_METHODID_DEVS         0x53564544 /* DEVice Set */
-#define ASUS_WMI_METHODID_CFVS         0x53564643 /* CPU Frequency Volt Set */
-#define ASUS_WMI_METHODID_KBFT         0x5446424B /* KeyBoard FilTer */
-#define ASUS_WMI_METHODID_INIT         0x54494E49 /* INITialize */
-#define ASUS_WMI_METHODID_HKEY         0x59454B48 /* Hot KEY ?? */
-
-#define ASUS_WMI_UNSUPPORTED_METHOD    0xFFFFFFFE
-
-/* Wireless */
-#define ASUS_WMI_DEVID_HW_SWITCH       0x00010001
-#define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
-#define ASUS_WMI_DEVID_CWAP            0x00010003
-#define ASUS_WMI_DEVID_WLAN            0x00010011
-#define ASUS_WMI_DEVID_WLAN_LED                0x00010012
-#define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
-#define ASUS_WMI_DEVID_GPS             0x00010015
-#define ASUS_WMI_DEVID_WIMAX           0x00010017
-#define ASUS_WMI_DEVID_WWAN3G          0x00010019
-#define ASUS_WMI_DEVID_UWB             0x00010021
-
-/* Leds */
-/* 0x000200XX and 0x000400XX */
-#define ASUS_WMI_DEVID_LED1            0x00020011
-#define ASUS_WMI_DEVID_LED2            0x00020012
-#define ASUS_WMI_DEVID_LED3            0x00020013
-#define ASUS_WMI_DEVID_LED4            0x00020014
-#define ASUS_WMI_DEVID_LED5            0x00020015
-#define ASUS_WMI_DEVID_LED6            0x00020016
-
-/* Backlight and Brightness */
-#define ASUS_WMI_DEVID_ALS_ENABLE      0x00050001 /* Ambient Light Sensor */
-#define ASUS_WMI_DEVID_BACKLIGHT       0x00050011
-#define ASUS_WMI_DEVID_BRIGHTNESS      0x00050012
-#define ASUS_WMI_DEVID_KBD_BACKLIGHT   0x00050021
-#define ASUS_WMI_DEVID_LIGHT_SENSOR    0x00050022 /* ?? */
-#define ASUS_WMI_DEVID_LIGHTBAR                0x00050025
-
-/* Misc */
-#define ASUS_WMI_DEVID_CAMERA          0x00060013
-
-/* Storage */
-#define ASUS_WMI_DEVID_CARDREADER      0x00080013
-
-/* Input */
-#define ASUS_WMI_DEVID_TOUCHPAD                0x00100011
-#define ASUS_WMI_DEVID_TOUCHPAD_LED    0x00100012
-
-/* Fan, Thermal */
-#define ASUS_WMI_DEVID_THERMAL_CTRL    0x00110011
-#define ASUS_WMI_DEVID_FAN_CTRL                0x00110012
-
-/* Power */
-#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
-
-/* Deep S3 / Resume on LID open */
-#define ASUS_WMI_DEVID_LID_RESUME      0x00120031
-
-/* DSTS masks */
-#define ASUS_WMI_DSTS_STATUS_BIT       0x00000001
-#define ASUS_WMI_DSTS_UNKNOWN_BIT      0x00000002
-#define ASUS_WMI_DSTS_PRESENCE_BIT     0x00010000
-#define ASUS_WMI_DSTS_USER_BIT         0x00020000
-#define ASUS_WMI_DSTS_BIOS_BIT         0x00040000
-#define ASUS_WMI_DSTS_BRIGHTNESS_MASK  0x000000FF
-#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK  0x0000FF00
-#define ASUS_WMI_DSTS_LIGHTBAR_MASK    0x0000000F
-
 #define ASUS_FAN_DESC                  "cpu_fan"
 #define ASUS_FAN_MFUN                  0x13
 #define ASUS_FAN_SFUN_READ             0x06
@@ -239,7 +157,6 @@ struct asus_wmi {
        int lightbar_led_wk;
        struct workqueue_struct *led_workqueue;
        struct work_struct tpd_led_work;
-       struct work_struct kbd_led_work;
        struct work_struct wlan_led_work;
        struct work_struct lightbar_led_work;
 
@@ -302,8 +219,7 @@ static void asus_wmi_input_exit(struct asus_wmi *asus)
        asus->inputdev = NULL;
 }
 
-static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
-                                   u32 *retval)
+int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval)
 {
        struct bios_args args = {
                .arg0 = arg0,
@@ -339,6 +255,7 @@ exit:
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(asus_wmi_evaluate_method);
 
 static int asus_wmi_evaluate_method_agfn(const struct acpi_buffer args)
 {
@@ -456,12 +373,9 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
        return read_tpd_led_state(asus);
 }
 
-static void kbd_led_update(struct work_struct *work)
+static void kbd_led_update(struct asus_wmi *asus)
 {
        int ctrl_param = 0;
-       struct asus_wmi *asus;
-
-       asus = container_of(work, struct asus_wmi, kbd_led_work);
 
        /*
         * bits 0-2: level
@@ -471,7 +385,6 @@ static void kbd_led_update(struct work_struct *work)
                ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
 
        asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
-       led_classdev_notify_brightness_hw_changed(&asus->kbd_led, asus->kbd_led_wk);
 }
 
 static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
@@ -516,7 +429,7 @@ static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
                value = 0;
 
        asus->kbd_led_wk = value;
-       queue_work(asus->led_workqueue, &asus->kbd_led_work);
+       kbd_led_update(asus);
 }
 
 static void kbd_led_set(struct led_classdev *led_cdev,
@@ -525,6 +438,14 @@ static void kbd_led_set(struct led_classdev *led_cdev,
        do_kbd_led_set(led_cdev, value);
 }
 
+static void kbd_led_set_by_kbd(struct asus_wmi *asus, enum led_brightness value)
+{
+       struct led_classdev *led_cdev = &asus->kbd_led;
+
+       do_kbd_led_set(led_cdev, value);
+       led_classdev_notify_brightness_hw_changed(led_cdev, asus->kbd_led_wk);
+}
+
 static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
 {
        struct asus_wmi *asus;
@@ -671,8 +592,6 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 
        led_val = kbd_led_read(asus, NULL, NULL);
        if (led_val >= 0) {
-               INIT_WORK(&asus->kbd_led_work, kbd_led_update);
-
                asus->kbd_led_wk = led_val;
                asus->kbd_led.name = "asus::kbd_backlight";
                asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
@@ -1746,18 +1665,18 @@ static void asus_wmi_notify(u32 value, void *context)
        }
 
        if (code == NOTIFY_KBD_BRTUP) {
-               do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1);
+               kbd_led_set_by_kbd(asus, asus->kbd_led_wk + 1);
                goto exit;
        }
        if (code == NOTIFY_KBD_BRTDWN) {
-               do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk - 1);
+               kbd_led_set_by_kbd(asus, asus->kbd_led_wk - 1);
                goto exit;
        }
        if (code == NOTIFY_KBD_BRTTOGGLE) {
                if (asus->kbd_led_wk == asus->kbd_led.max_brightness)
-                       do_kbd_led_set(&asus->kbd_led, 0);
+                       kbd_led_set_by_kbd(asus, 0);
                else
-                       do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1);
+                       kbd_led_set_by_kbd(asus, asus->kbd_led_wk + 1);
                goto exit;
        }
 
@@ -2291,7 +2210,7 @@ static int asus_hotk_resume(struct device *device)
        struct asus_wmi *asus = dev_get_drvdata(device);
 
        if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
-               queue_work(asus->led_workqueue, &asus->kbd_led_work);
+               kbd_led_update(asus);
 
        return 0;
 }
@@ -2327,7 +2246,7 @@ static int asus_hotk_restore(struct device *device)
                rfkill_set_sw_state(asus->uwb.rfkill, bl);
        }
        if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
-               queue_work(asus->led_workqueue, &asus->kbd_led_work);
+               kbd_led_update(asus);
 
        return 0;
 }
diff --git a/drivers/platform/x86/dcdbas.c b/drivers/platform/x86/dcdbas.c
new file mode 100644 (file)
index 0000000..88bd7ef
--- /dev/null
@@ -0,0 +1,761 @@
+/*
+ *  dcdbas.c: Dell Systems Management Base Driver
+ *
+ *  The Dell Systems Management Base Driver provides a sysfs interface for
+ *  systems management software to perform System Management Interrupts (SMIs)
+ *  and Host Control Actions (power cycle or power off after OS shutdown) on
+ *  Dell systems.
+ *
+ *  See Documentation/dcdbas.txt for more information.
+ *
+ *  Copyright (C) 1995-2006 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License v2.0 as published by
+ *  the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/cpu.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+
+#include "dcdbas.h"
+
+#define DRIVER_NAME            "dcdbas"
+#define DRIVER_VERSION         "5.6.0-3.3"
+#define DRIVER_DESCRIPTION     "Dell Systems Management Base Driver"
+
+static struct platform_device *dcdbas_pdev;
+
+static u8 *smi_data_buf;
+static dma_addr_t smi_data_buf_handle;
+static unsigned long smi_data_buf_size;
+static unsigned long max_smi_data_buf_size = MAX_SMI_DATA_BUF_SIZE;
+static u32 smi_data_buf_phys_addr;
+static DEFINE_MUTEX(smi_data_lock);
+static u8 *eps_buffer;
+
+static unsigned int host_control_action;
+static unsigned int host_control_smi_type;
+static unsigned int host_control_on_shutdown;
+
+static bool wsmt_enabled;
+
+/**
+ * smi_data_buf_free: free SMI data buffer
+ */
+static void smi_data_buf_free(void)
+{
+       if (!smi_data_buf || wsmt_enabled)
+               return;
+
+       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+       dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
+                         smi_data_buf_handle);
+       smi_data_buf = NULL;
+       smi_data_buf_handle = 0;
+       smi_data_buf_phys_addr = 0;
+       smi_data_buf_size = 0;
+}
+
+/**
+ * smi_data_buf_realloc: grow SMI data buffer if needed
+ */
+static int smi_data_buf_realloc(unsigned long size)
+{
+       void *buf;
+       dma_addr_t handle;
+
+       if (smi_data_buf_size >= size)
+               return 0;
+
+       if (size > max_smi_data_buf_size)
+               return -EINVAL;
+
+       /* new buffer is needed */
+       buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL);
+       if (!buf) {
+               dev_dbg(&dcdbas_pdev->dev,
+                       "%s: failed to allocate memory size %lu\n",
+                       __func__, size);
+               return -ENOMEM;
+       }
+       /* memory zeroed by dma_alloc_coherent */
+
+       if (smi_data_buf)
+               memcpy(buf, smi_data_buf, smi_data_buf_size);
+
+       /* free any existing buffer */
+       smi_data_buf_free();
+
+       /* set up new buffer for use */
+       smi_data_buf = buf;
+       smi_data_buf_handle = handle;
+       smi_data_buf_phys_addr = (u32) virt_to_phys(buf);
+       smi_data_buf_size = size;
+
+       dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
+               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
+
+       return 0;
+}
+
+static ssize_t smi_data_buf_phys_addr_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       return sprintf(buf, "%x\n", smi_data_buf_phys_addr);
+}
+
+static ssize_t smi_data_buf_size_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       return sprintf(buf, "%lu\n", smi_data_buf_size);
+}
+
+static ssize_t smi_data_buf_size_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       unsigned long buf_size;
+       ssize_t ret;
+
+       buf_size = simple_strtoul(buf, NULL, 10);
+
+       /* make sure SMI data buffer is at least buf_size */
+       mutex_lock(&smi_data_lock);
+       ret = smi_data_buf_realloc(buf_size);
+       mutex_unlock(&smi_data_lock);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static ssize_t smi_data_read(struct file *filp, struct kobject *kobj,
+                            struct bin_attribute *bin_attr,
+                            char *buf, loff_t pos, size_t count)
+{
+       ssize_t ret;
+
+       mutex_lock(&smi_data_lock);
+       ret = memory_read_from_buffer(buf, count, &pos, smi_data_buf,
+                                       smi_data_buf_size);
+       mutex_unlock(&smi_data_lock);
+       return ret;
+}
+
+static ssize_t smi_data_write(struct file *filp, struct kobject *kobj,
+                             struct bin_attribute *bin_attr,
+                             char *buf, loff_t pos, size_t count)
+{
+       ssize_t ret;
+
+       if ((pos + count) > max_smi_data_buf_size)
+               return -EINVAL;
+
+       mutex_lock(&smi_data_lock);
+
+       ret = smi_data_buf_realloc(pos + count);
+       if (ret)
+               goto out;
+
+       memcpy(smi_data_buf + pos, buf, count);
+       ret = count;
+out:
+       mutex_unlock(&smi_data_lock);
+       return ret;
+}
+
+static ssize_t host_control_action_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_action);
+}
+
+static ssize_t host_control_action_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       ssize_t ret;
+
+       /* make sure buffer is available for host control command */
+       mutex_lock(&smi_data_lock);
+       ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
+       mutex_unlock(&smi_data_lock);
+       if (ret)
+               return ret;
+
+       host_control_action = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+static ssize_t host_control_smi_type_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_smi_type);
+}
+
+static ssize_t host_control_smi_type_store(struct device *dev,
+                                          struct device_attribute *attr,
+                                          const char *buf, size_t count)
+{
+       host_control_smi_type = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+static ssize_t host_control_on_shutdown_show(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       return sprintf(buf, "%u\n", host_control_on_shutdown);
+}
+
+static ssize_t host_control_on_shutdown_store(struct device *dev,
+                                             struct device_attribute *attr,
+                                             const char *buf, size_t count)
+{
+       host_control_on_shutdown = simple_strtoul(buf, NULL, 10);
+       return count;
+}
+
+static int raise_smi(void *par)
+{
+       struct smi_cmd *smi_cmd = par;
+
+       if (smp_processor_id() != 0) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
+                       __func__);
+               return -EBUSY;
+       }
+
+       /* generate SMI */
+       /* inb to force posted write through and make SMI happen now */
+       asm volatile (
+               "outb %b0,%w1\n"
+               "inb %w1"
+               : /* no output args */
+               : "a" (smi_cmd->command_code),
+                 "d" (smi_cmd->command_address),
+                 "b" (smi_cmd->ebx),
+                 "c" (smi_cmd->ecx)
+               : "memory"
+       );
+
+       return 0;
+}
+/**
+ * dcdbas_smi_request: generate SMI request
+ *
+ * Called with smi_data_lock.
+ */
+int dcdbas_smi_request(struct smi_cmd *smi_cmd)
+{
+       int ret;
+
+       if (smi_cmd->magic != SMI_CMD_MAGIC) {
+               dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
+                        __func__);
+               return -EBADR;
+       }
+
+       /* SMI requires CPU 0 */
+       get_online_cpus();
+       ret = smp_call_on_cpu(0, raise_smi, smi_cmd, true);
+       put_online_cpus();
+
+       return ret;
+}
+
+/**
+ * smi_request_store:
+ *
+ * The valid values are:
+ * 0: zero SMI data buffer
+ * 1: generate calling interface SMI
+ * 2: generate raw SMI
+ *
+ * User application writes smi_cmd to smi_data before telling driver
+ * to generate SMI.
+ */
+static ssize_t smi_request_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct smi_cmd *smi_cmd;
+       unsigned long val = simple_strtoul(buf, NULL, 10);
+       ssize_t ret;
+
+       mutex_lock(&smi_data_lock);
+
+       if (smi_data_buf_size < sizeof(struct smi_cmd)) {
+               ret = -ENODEV;
+               goto out;
+       }
+       smi_cmd = (struct smi_cmd *)smi_data_buf;
+
+       switch (val) {
+       case 2:
+               /* Raw SMI */
+               ret = dcdbas_smi_request(smi_cmd);
+               if (!ret)
+                       ret = count;
+               break;
+       case 1:
+               /*
+                * Calling Interface SMI
+                *
+                * Provide physical address of command buffer field within
+                * the struct smi_cmd to BIOS.
+                *
+                * Because the address that smi_cmd (smi_data_buf) points to
+                * will be from memremap() of a non-memory address if WSMT
+                * is present, we can't use virt_to_phys() on smi_cmd, so
+                * we have to use the physical address that was saved when
+                * the virtual address for smi_cmd was received.
+                */
+               smi_cmd->ebx = smi_data_buf_phys_addr +
+                               offsetof(struct smi_cmd, command_buffer);
+               ret = dcdbas_smi_request(smi_cmd);
+               if (!ret)
+                       ret = count;
+               break;
+       case 0:
+               memset(smi_data_buf, 0, smi_data_buf_size);
+               ret = count;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+out:
+       mutex_unlock(&smi_data_lock);
+       return ret;
+}
+EXPORT_SYMBOL(dcdbas_smi_request);
+
+/**
+ * host_control_smi: generate host control SMI
+ *
+ * Caller must set up the host control command in smi_data_buf.
+ */
+static int host_control_smi(void)
+{
+       struct apm_cmd *apm_cmd;
+       u8 *data;
+       unsigned long flags;
+       u32 num_ticks;
+       s8 cmd_status;
+       u8 index;
+
+       apm_cmd = (struct apm_cmd *)smi_data_buf;
+       apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL;
+
+       switch (host_control_smi_type) {
+       case HC_SMITYPE_TYPE1:
+               spin_lock_irqsave(&rtc_lock, flags);
+               /* write SMI data buffer physical address */
+               data = (u8 *)&smi_data_buf_phys_addr;
+               for (index = PE1300_CMOS_CMD_STRUCT_PTR;
+                    index < (PE1300_CMOS_CMD_STRUCT_PTR + 4);
+                    index++, data++) {
+                       outb(index,
+                            (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4));
+                       outb(*data,
+                            (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4));
+               }
+
+               /* first set status to -1 as called by spec */
+               cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL;
+               outb((u8) cmd_status, PCAT_APM_STATUS_PORT);
+
+               /* generate SMM call */
+               outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+               spin_unlock_irqrestore(&rtc_lock, flags);
+
+               /* wait a few to see if it executed */
+               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+               while ((cmd_status = inb(PCAT_APM_STATUS_PORT))
+                      == ESM_STATUS_CMD_UNSUCCESSFUL) {
+                       num_ticks--;
+                       if (num_ticks == EXPIRED_TIMER)
+                               return -ETIME;
+               }
+               break;
+
+       case HC_SMITYPE_TYPE2:
+       case HC_SMITYPE_TYPE3:
+               spin_lock_irqsave(&rtc_lock, flags);
+               /* write SMI data buffer physical address */
+               data = (u8 *)&smi_data_buf_phys_addr;
+               for (index = PE1400_CMOS_CMD_STRUCT_PTR;
+                    index < (PE1400_CMOS_CMD_STRUCT_PTR + 4);
+                    index++, data++) {
+                       outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT));
+                       outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT));
+               }
+
+               /* generate SMM call */
+               if (host_control_smi_type == HC_SMITYPE_TYPE3)
+                       outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT);
+               else
+                       outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT);
+
+               /* restore RTC index pointer since it was written to above */
+               CMOS_READ(RTC_REG_C);
+               spin_unlock_irqrestore(&rtc_lock, flags);
+
+               /* read control port back to serialize write */
+               cmd_status = inb(PE1400_APM_CONTROL_PORT);
+
+               /* wait a few to see if it executed */
+               num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING;
+               while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) {
+                       num_ticks--;
+                       if (num_ticks == EXPIRED_TIMER)
+                               return -ETIME;
+               }
+               break;
+
+       default:
+               dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
+                       __func__, host_control_smi_type);
+               return -ENOSYS;
+       }
+
+       return 0;
+}
+
+/**
+ * dcdbas_host_control: initiate host control
+ *
+ * This function is called by the driver after the system has
+ * finished shutting down if the user application specified a
+ * host control action to perform on shutdown.  It is safe to
+ * use smi_data_buf at this point because the system has finished
+ * shutting down and no userspace apps are running.
+ */
+static void dcdbas_host_control(void)
+{
+       struct apm_cmd *apm_cmd;
+       u8 action;
+
+       if (host_control_action == HC_ACTION_NONE)
+               return;
+
+       action = host_control_action;
+       host_control_action = HC_ACTION_NONE;
+
+       if (!smi_data_buf) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __func__);
+               return;
+       }
+
+       if (smi_data_buf_size < sizeof(struct apm_cmd)) {
+               dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
+                       __func__);
+               return;
+       }
+
+       apm_cmd = (struct apm_cmd *)smi_data_buf;
+
+       /* power off takes precedence */
+       if (action & HC_ACTION_HOST_CONTROL_POWEROFF) {
+               apm_cmd->command = ESM_APM_POWER_CYCLE;
+               apm_cmd->reserved = 0;
+               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0;
+               host_control_smi();
+       } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) {
+               apm_cmd->command = ESM_APM_POWER_CYCLE;
+               apm_cmd->reserved = 0;
+               *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20;
+               host_control_smi();
+       }
+}
+
+/* WSMT */
+
+static u8 checksum(u8 *buffer, u8 length)
+{
+       u8 sum = 0;
+       u8 *end = buffer + length;
+
+       while (buffer < end)
+               sum += *buffer++;
+       return sum;
+}
+
+static inline struct smm_eps_table *check_eps_table(u8 *addr)
+{
+       struct smm_eps_table *eps = (struct smm_eps_table *)addr;
+
+       if (strncmp(eps->smm_comm_buff_anchor, SMM_EPS_SIG, 4) != 0)
+               return NULL;
+
+       if (checksum(addr, eps->length) != 0)
+               return NULL;
+
+       return eps;
+}
+
+static int dcdbas_check_wsmt(void)
+{
+       struct acpi_table_wsmt *wsmt = NULL;
+       struct smm_eps_table *eps = NULL;
+       u64 remap_size;
+       u8 *addr;
+
+       acpi_get_table(ACPI_SIG_WSMT, 0, (struct acpi_table_header **)&wsmt);
+       if (!wsmt)
+               return 0;
+
+       /* Check if WSMT ACPI table shows that protection is enabled */
+       if (!(wsmt->protection_flags & ACPI_WSMT_FIXED_COMM_BUFFERS) ||
+           !(wsmt->protection_flags & ACPI_WSMT_COMM_BUFFER_NESTED_PTR_PROTECTION))
+               return 0;
+
+       /* Scan for EPS (entry point structure) */
+       for (addr = (u8 *)__va(0xf0000);
+            addr < (u8 *)__va(0x100000 - sizeof(struct smm_eps_table));
+            addr += 16) {
+               eps = check_eps_table(addr);
+               if (eps)
+                       break;
+       }
+
+       if (!eps) {
+               dev_dbg(&dcdbas_pdev->dev, "found WSMT, but no EPS found\n");
+               return -ENODEV;
+       }
+
+       /*
+        * Get physical address of buffer and map to virtual address.
+        * Table gives size in 4K pages, regardless of actual system page size.
+        */
+       if (upper_32_bits(eps->smm_comm_buff_addr + 8)) {
+               dev_warn(&dcdbas_pdev->dev, "found WSMT, but EPS buffer address is above 4GB\n");
+               return -EINVAL;
+       }
+       /*
+        * Limit remap size to MAX_SMI_DATA_BUF_SIZE + 8 (since the first 8
+        * bytes are used for a semaphore, not the data buffer itself).
+        */
+       remap_size = eps->num_of_4k_pages * PAGE_SIZE;
+       if (remap_size > MAX_SMI_DATA_BUF_SIZE + 8)
+               remap_size = MAX_SMI_DATA_BUF_SIZE + 8;
+       eps_buffer = memremap(eps->smm_comm_buff_addr, remap_size, MEMREMAP_WB);
+       if (!eps_buffer) {
+               dev_warn(&dcdbas_pdev->dev, "found WSMT, but failed to map EPS buffer\n");
+               return -ENOMEM;
+       }
+
+       /* First 8 bytes is for a semaphore, not part of the smi_data_buf */
+       smi_data_buf_phys_addr = eps->smm_comm_buff_addr + 8;
+       smi_data_buf = eps_buffer + 8;
+       smi_data_buf_size = remap_size - 8;
+       max_smi_data_buf_size = smi_data_buf_size;
+       wsmt_enabled = true;
+       dev_info(&dcdbas_pdev->dev,
+                "WSMT found, using firmware-provided SMI buffer.\n");
+       return 1;
+}
+
+/**
+ * dcdbas_reboot_notify: handle reboot notification for host control
+ */
+static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
+                               void *unused)
+{
+       switch (code) {
+       case SYS_DOWN:
+       case SYS_HALT:
+       case SYS_POWER_OFF:
+               if (host_control_on_shutdown) {
+                       /* firmware is going to perform host control action */
+                       printk(KERN_WARNING "Please wait for shutdown "
+                              "action to complete...\n");
+                       dcdbas_host_control();
+               }
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block dcdbas_reboot_nb = {
+       .notifier_call = dcdbas_reboot_notify,
+       .next = NULL,
+       .priority = INT_MIN
+};
+
+static DCDBAS_BIN_ATTR_RW(smi_data);
+
+static struct bin_attribute *dcdbas_bin_attrs[] = {
+       &bin_attr_smi_data,
+       NULL
+};
+
+static DCDBAS_DEV_ATTR_RW(smi_data_buf_size);
+static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr);
+static DCDBAS_DEV_ATTR_WO(smi_request);
+static DCDBAS_DEV_ATTR_RW(host_control_action);
+static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
+static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
+
+static struct attribute *dcdbas_dev_attrs[] = {
+       &dev_attr_smi_data_buf_size.attr,
+       &dev_attr_smi_data_buf_phys_addr.attr,
+       &dev_attr_smi_request.attr,
+       &dev_attr_host_control_action.attr,
+       &dev_attr_host_control_smi_type.attr,
+       &dev_attr_host_control_on_shutdown.attr,
+       NULL
+};
+
+static const struct attribute_group dcdbas_attr_group = {
+       .attrs = dcdbas_dev_attrs,
+       .bin_attrs = dcdbas_bin_attrs,
+};
+
+static int dcdbas_probe(struct platform_device *dev)
+{
+       int error;
+
+       host_control_action = HC_ACTION_NONE;
+       host_control_smi_type = HC_SMITYPE_NONE;
+
+       dcdbas_pdev = dev;
+
+       /* Check if ACPI WSMT table specifies protected SMI buffer address */
+       error = dcdbas_check_wsmt();
+       if (error < 0)
+               return error;
+
+       /*
+        * BIOS SMI calls require buffer addresses be in 32-bit address space.
+        * This is done by setting the DMA mask below.
+        */
+       error = dma_set_coherent_mask(&dcdbas_pdev->dev, DMA_BIT_MASK(32));
+       if (error)
+               return error;
+
+       error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
+       if (error)
+               return error;
+
+       register_reboot_notifier(&dcdbas_reboot_nb);
+
+       dev_info(&dev->dev, "%s (version %s)\n",
+                DRIVER_DESCRIPTION, DRIVER_VERSION);
+
+       return 0;
+}
+
+static int dcdbas_remove(struct platform_device *dev)
+{
+       unregister_reboot_notifier(&dcdbas_reboot_nb);
+       sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
+
+       return 0;
+}
+
+static struct platform_driver dcdbas_driver = {
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+       .probe          = dcdbas_probe,
+       .remove         = dcdbas_remove,
+};
+
+static const struct platform_device_info dcdbas_dev_info __initconst = {
+       .name           = DRIVER_NAME,
+       .id             = -1,
+       .dma_mask       = DMA_BIT_MASK(32),
+};
+
+static struct platform_device *dcdbas_pdev_reg;
+
+/**
+ * dcdbas_init: initialize driver
+ */
+static int __init dcdbas_init(void)
+{
+       int error;
+
+       error = platform_driver_register(&dcdbas_driver);
+       if (error)
+               return error;
+
+       dcdbas_pdev_reg = platform_device_register_full(&dcdbas_dev_info);
+       if (IS_ERR(dcdbas_pdev_reg)) {
+               error = PTR_ERR(dcdbas_pdev_reg);
+               goto err_unregister_driver;
+       }
+
+       return 0;
+
+ err_unregister_driver:
+       platform_driver_unregister(&dcdbas_driver);
+       return error;
+}
+
+/**
+ * dcdbas_exit: perform driver cleanup
+ */
+static void __exit dcdbas_exit(void)
+{
+       /*
+        * make sure functions that use dcdbas_pdev are called
+        * before platform_device_unregister
+        */
+       unregister_reboot_notifier(&dcdbas_reboot_nb);
+
+       /*
+        * We have to free the buffer here instead of dcdbas_remove
+        * because only in module exit function we can be sure that
+        * all sysfs attributes belonging to this module have been
+        * released.
+        */
+       if (dcdbas_pdev)
+               smi_data_buf_free();
+       if (eps_buffer)
+               memunmap(eps_buffer);
+       platform_device_unregister(dcdbas_pdev_reg);
+       platform_driver_unregister(&dcdbas_driver);
+}
+
+subsys_initcall_sync(dcdbas_init);
+module_exit(dcdbas_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")");
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Dell Inc.");
+MODULE_LICENSE("GPL");
+/* Any System or BIOS claiming to be by Dell */
+MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*");
diff --git a/drivers/platform/x86/dcdbas.h b/drivers/platform/x86/dcdbas.h
new file mode 100644 (file)
index 0000000..52729a4
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  dcdbas.h: Definitions for Dell Systems Management Base driver
+ *
+ *  Copyright (C) 1995-2005 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License v2.0 as published by
+ *  the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#ifndef _DCDBAS_H_
+#define _DCDBAS_H_
+
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#define MAX_SMI_DATA_BUF_SIZE                  (256 * 1024)
+
+#define HC_ACTION_NONE                         (0)
+#define HC_ACTION_HOST_CONTROL_POWEROFF                BIT(1)
+#define HC_ACTION_HOST_CONTROL_POWERCYCLE      BIT(2)
+
+#define HC_SMITYPE_NONE                                (0)
+#define HC_SMITYPE_TYPE1                       (1)
+#define HC_SMITYPE_TYPE2                       (2)
+#define HC_SMITYPE_TYPE3                       (3)
+
+#define ESM_APM_CMD                            (0x0A0)
+#define ESM_APM_POWER_CYCLE                    (0x10)
+#define ESM_STATUS_CMD_UNSUCCESSFUL            (-1)
+
+#define CMOS_BASE_PORT                         (0x070)
+#define CMOS_PAGE1_INDEX_PORT                  (0)
+#define CMOS_PAGE1_DATA_PORT                   (1)
+#define CMOS_PAGE2_INDEX_PORT_PIIX4            (2)
+#define CMOS_PAGE2_DATA_PORT_PIIX4             (3)
+#define PE1400_APM_CONTROL_PORT                        (0x0B0)
+#define PCAT_APM_CONTROL_PORT                  (0x0B2)
+#define PCAT_APM_STATUS_PORT                   (0x0B3)
+#define PE1300_CMOS_CMD_STRUCT_PTR             (0x38)
+#define PE1400_CMOS_CMD_STRUCT_PTR             (0x70)
+
+#define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN       (14)
+#define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM                (16)
+
+#define TIMEOUT_USEC_SHORT_SEMA_BLOCKING       (10000)
+#define EXPIRED_TIMER                          (0)
+
+#define SMI_CMD_MAGIC                          (0x534D4931)
+#define SMM_EPS_SIG                            "$SCB"
+
+#define DCDBAS_DEV_ATTR_RW(_name) \
+       DEVICE_ATTR(_name,0600,_name##_show,_name##_store);
+
+#define DCDBAS_DEV_ATTR_RO(_name) \
+       DEVICE_ATTR(_name,0400,_name##_show,NULL);
+
+#define DCDBAS_DEV_ATTR_WO(_name) \
+       DEVICE_ATTR(_name,0200,NULL,_name##_store);
+
+#define DCDBAS_BIN_ATTR_RW(_name) \
+struct bin_attribute bin_attr_##_name = { \
+       .attr =  { .name = __stringify(_name), \
+                  .mode = 0600 }, \
+       .read =  _name##_read, \
+       .write = _name##_write, \
+}
+
+struct smi_cmd {
+       __u32 magic;
+       __u32 ebx;
+       __u32 ecx;
+       __u16 command_address;
+       __u8 command_code;
+       __u8 reserved;
+       __u8 command_buffer[1];
+} __attribute__ ((packed));
+
+struct apm_cmd {
+       __u8 command;
+       __s8 status;
+       __u16 reserved;
+       union {
+               struct {
+                       __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN];
+               } __attribute__ ((packed)) shortreq;
+
+               struct {
+                       __u16 num_sg_entries;
+                       struct {
+                               __u32 size;
+                               __u64 addr;
+                       } __attribute__ ((packed))
+                           sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM];
+               } __attribute__ ((packed)) longreq;
+       } __attribute__ ((packed)) parameters;
+} __attribute__ ((packed));
+
+int dcdbas_smi_request(struct smi_cmd *smi_cmd);
+
+struct smm_eps_table {
+       char smm_comm_buff_anchor[4];
+       u8 length;
+       u8 checksum;
+       u8 version;
+       u64 smm_comm_buff_addr;
+       u64 num_of_4k_pages;
+} __packed;
+
+#endif /* _DCDBAS_H_ */
+
index 97a90bebc36079f5ff716b8d739bd27928aa442a..ab9b822a6dfe6df42a0ba237f7aa50fb984d39db 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
-#include "../../firmware/dcdbas.h"
+#include "dcdbas.h"
 #include "dell-smbios.h"
 
 static int da_command_address;
diff --git a/drivers/platform/x86/dell_rbu.c b/drivers/platform/x86/dell_rbu.c
new file mode 100644 (file)
index 0000000..ccefa84
--- /dev/null
@@ -0,0 +1,753 @@
+/*
+ * dell_rbu.c
+ * Bios Update driver for Dell systems
+ * Author: Dell Inc
+ *         Abhay Salunke <abhay_salunke@dell.com>
+ *
+ * Copyright (C) 2005 Dell Inc.
+ *
+ * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
+ * creating entries in the /sys file systems on Linux 2.6 and higher
+ * kernels. The driver supports two mechanism to update the BIOS namely
+ * contiguous and packetized. Both these methods still require having some
+ * application to set the CMOS bit indicating the BIOS to update itself
+ * after a reboot.
+ *
+ * Contiguous method:
+ * This driver writes the incoming data in a monolithic image by allocating
+ * contiguous physical pages large enough to accommodate the incoming BIOS
+ * image size.
+ *
+ * Packetized method:
+ * The driver writes the incoming packet image by allocating a new packet
+ * on every time the packet data is written. This driver requires an
+ * application to break the BIOS image in to fixed sized packet chunks.
+ *
+ * See Documentation/dell_rbu.txt for more info.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License v2.0 as published by
+ * the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/dma-mapping.h>
+#include <asm/set_memory.h>
+
+MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
+MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("3.2");
+
+#define BIOS_SCAN_LIMIT 0xffffffff
+#define MAX_IMAGE_LENGTH 16
+static struct _rbu_data {
+       void *image_update_buffer;
+       unsigned long image_update_buffer_size;
+       unsigned long bios_image_size;
+       int image_update_ordernum;
+       int dma_alloc;
+       spinlock_t lock;
+       unsigned long packet_read_count;
+       unsigned long num_packets;
+       unsigned long packetsize;
+       unsigned long imagesize;
+       int entry_created;
+} rbu_data;
+
+static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
+module_param_string(image_type, image_type, sizeof (image_type), 0);
+MODULE_PARM_DESC(image_type,
+       "BIOS image type. choose- mono or packet or init");
+
+static unsigned long allocation_floor = 0x100000;
+module_param(allocation_floor, ulong, 0644);
+MODULE_PARM_DESC(allocation_floor,
+    "Minimum address for allocations when using Packet mode");
+
+struct packet_data {
+       struct list_head list;
+       size_t length;
+       void *data;
+       int ordernum;
+};
+
+static struct packet_data packet_data_head;
+
+static struct platform_device *rbu_device;
+static int context;
+static dma_addr_t dell_rbu_dmaaddr;
+
+static void init_packet_head(void)
+{
+       INIT_LIST_HEAD(&packet_data_head.list);
+       rbu_data.packet_read_count = 0;
+       rbu_data.num_packets = 0;
+       rbu_data.packetsize = 0;
+       rbu_data.imagesize = 0;
+}
+
+static int create_packet(void *data, size_t length)
+{
+       struct packet_data *newpacket;
+       int ordernum = 0;
+       int retval = 0;
+       unsigned int packet_array_size = 0;
+       void **invalid_addr_packet_array = NULL;
+       void *packet_data_temp_buf = NULL;
+       unsigned int idx = 0;
+
+       pr_debug("create_packet: entry \n");
+
+       if (!rbu_data.packetsize) {
+               pr_debug("create_packet: packetsize not specified\n");
+               retval = -EINVAL;
+               goto out_noalloc;
+       }
+
+       spin_unlock(&rbu_data.lock);
+
+       newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
+
+       if (!newpacket) {
+               printk(KERN_WARNING
+                       "dell_rbu:%s: failed to allocate new "
+                       "packet\n", __func__);
+               retval = -ENOMEM;
+               spin_lock(&rbu_data.lock);
+               goto out_noalloc;
+       }
+
+       ordernum = get_order(length);
+
+       /*
+        * BIOS errata mean we cannot allocate packets below 1MB or they will
+        * be overwritten by BIOS.
+        *
+        * array to temporarily hold packets
+        * that are below the allocation floor
+        *
+        * NOTE: very simplistic because we only need the floor to be at 1MB
+        *       due to BIOS errata. This shouldn't be used for higher floors
+        *       or you will run out of mem trying to allocate the array.
+        */
+       packet_array_size = max(
+                       (unsigned int)(allocation_floor / rbu_data.packetsize),
+                       (unsigned int)1);
+       invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *),
+                                               GFP_KERNEL);
+
+       if (!invalid_addr_packet_array) {
+               printk(KERN_WARNING
+                       "dell_rbu:%s: failed to allocate "
+                       "invalid_addr_packet_array \n",
+                       __func__);
+               retval = -ENOMEM;
+               spin_lock(&rbu_data.lock);
+               goto out_alloc_packet;
+       }
+
+       while (!packet_data_temp_buf) {
+               packet_data_temp_buf = (unsigned char *)
+                       __get_free_pages(GFP_KERNEL, ordernum);
+               if (!packet_data_temp_buf) {
+                       printk(KERN_WARNING
+                               "dell_rbu:%s: failed to allocate new "
+                               "packet\n", __func__);
+                       retval = -ENOMEM;
+                       spin_lock(&rbu_data.lock);
+                       goto out_alloc_packet_array;
+               }
+
+               if ((unsigned long)virt_to_phys(packet_data_temp_buf)
+                               < allocation_floor) {
+                       pr_debug("packet 0x%lx below floor at 0x%lx.\n",
+                                       (unsigned long)virt_to_phys(
+                                               packet_data_temp_buf),
+                                       allocation_floor);
+                       invalid_addr_packet_array[idx++] = packet_data_temp_buf;
+                       packet_data_temp_buf = NULL;
+               }
+       }
+       /*
+        * set to uncachable or it may never get written back before reboot
+        */
+       set_memory_uc((unsigned long)packet_data_temp_buf, 1 << ordernum);
+
+       spin_lock(&rbu_data.lock);
+
+       newpacket->data = packet_data_temp_buf;
+
+       pr_debug("create_packet: newpacket at physical addr %lx\n",
+               (unsigned long)virt_to_phys(newpacket->data));
+
+       /* packets may not have fixed size */
+       newpacket->length = length;
+       newpacket->ordernum = ordernum;
+       ++rbu_data.num_packets;
+
+       /* initialize the newly created packet headers */
+       INIT_LIST_HEAD(&newpacket->list);
+       list_add_tail(&newpacket->list, &packet_data_head.list);
+
+       memcpy(newpacket->data, data, length);
+
+       pr_debug("create_packet: exit \n");
+
+out_alloc_packet_array:
+       /* always free packet array */
+       for (;idx>0;idx--) {
+               pr_debug("freeing unused packet below floor 0x%lx.\n",
+                       (unsigned long)virt_to_phys(
+                               invalid_addr_packet_array[idx-1]));
+               free_pages((unsigned long)invalid_addr_packet_array[idx-1],
+                       ordernum);
+       }
+       kfree(invalid_addr_packet_array);
+
+out_alloc_packet:
+       /* if error, free data */
+       if (retval)
+               kfree(newpacket);
+
+out_noalloc:
+       return retval;
+}
+
+static int packetize_data(const u8 *data, size_t length)
+{
+       int rc = 0;
+       int done = 0;
+       int packet_length;
+       u8 *temp;
+       u8 *end = (u8 *) data + length;
+       pr_debug("packetize_data: data length %zd\n", length);
+       if (!rbu_data.packetsize) {
+               printk(KERN_WARNING
+                       "dell_rbu: packetsize not specified\n");
+               return -EIO;
+       }
+
+       temp = (u8 *) data;
+
+       /* packetize the hunk */
+       while (!done) {
+               if ((temp + rbu_data.packetsize) < end)
+                       packet_length = rbu_data.packetsize;
+               else {
+                       /* this is the last packet */
+                       packet_length = end - temp;
+                       done = 1;
+               }
+
+               if ((rc = create_packet(temp, packet_length)))
+                       return rc;
+
+               pr_debug("%p:%td\n", temp, (end - temp));
+               temp += packet_length;
+       }
+
+       rbu_data.imagesize = length;
+
+       return rc;
+}
+
+static int do_packet_read(char *data, struct list_head *ptemp_list,
+       int length, int bytes_read, int *list_read_count)
+{
+       void *ptemp_buf;
+       struct packet_data *newpacket = NULL;
+       int bytes_copied = 0;
+       int j = 0;
+
+       newpacket = list_entry(ptemp_list, struct packet_data, list);
+       *list_read_count += newpacket->length;
+
+       if (*list_read_count > bytes_read) {
+               /* point to the start of unread data */
+               j = newpacket->length - (*list_read_count - bytes_read);
+               /* point to the offset in the packet buffer */
+               ptemp_buf = (u8 *) newpacket->data + j;
+               /*
+                * check if there is enough room in
+                * * the incoming buffer
+                */
+               if (length > (*list_read_count - bytes_read))
+                       /*
+                        * copy what ever is there in this
+                        * packet and move on
+                        */
+                       bytes_copied = (*list_read_count - bytes_read);
+               else
+                       /* copy the remaining */
+                       bytes_copied = length;
+               memcpy(data, ptemp_buf, bytes_copied);
+       }
+       return bytes_copied;
+}
+
+static int packet_read_list(char *data, size_t * pread_length)
+{
+       struct list_head *ptemp_list;
+       int temp_count = 0;
+       int bytes_copied = 0;
+       int bytes_read = 0;
+       int remaining_bytes = 0;
+       char *pdest = data;
+
+       /* check if we have any packets */
+       if (0 == rbu_data.num_packets)
+               return -ENOMEM;
+
+       remaining_bytes = *pread_length;
+       bytes_read = rbu_data.packet_read_count;
+
+       ptemp_list = (&packet_data_head.list)->next;
+       while (!list_empty(ptemp_list)) {
+               bytes_copied = do_packet_read(pdest, ptemp_list,
+                       remaining_bytes, bytes_read, &temp_count);
+               remaining_bytes -= bytes_copied;
+               bytes_read += bytes_copied;
+               pdest += bytes_copied;
+               /*
+                * check if we reached end of buffer before reaching the
+                * last packet
+                */
+               if (remaining_bytes == 0)
+                       break;
+
+               ptemp_list = ptemp_list->next;
+       }
+       /*finally set the bytes read */
+       *pread_length = bytes_read - rbu_data.packet_read_count;
+       rbu_data.packet_read_count = bytes_read;
+       return 0;
+}
+
+static void packet_empty_list(void)
+{
+       struct list_head *ptemp_list;
+       struct list_head *pnext_list;
+       struct packet_data *newpacket;
+
+       ptemp_list = (&packet_data_head.list)->next;
+       while (!list_empty(ptemp_list)) {
+               newpacket =
+                       list_entry(ptemp_list, struct packet_data, list);
+               pnext_list = ptemp_list->next;
+               list_del(ptemp_list);
+               ptemp_list = pnext_list;
+               /*
+                * zero out the RBU packet memory before freeing
+                * to make sure there are no stale RBU packets left in memory
+                */
+               memset(newpacket->data, 0, rbu_data.packetsize);
+               set_memory_wb((unsigned long)newpacket->data,
+                       1 << newpacket->ordernum);
+               free_pages((unsigned long) newpacket->data,
+                       newpacket->ordernum);
+               kfree(newpacket);
+       }
+       rbu_data.packet_read_count = 0;
+       rbu_data.num_packets = 0;
+       rbu_data.imagesize = 0;
+}
+
+/*
+ * img_update_free: Frees the buffer allocated for storing BIOS image
+ * Always called with lock held and returned with lock held
+ */
+static void img_update_free(void)
+{
+       if (!rbu_data.image_update_buffer)
+               return;
+       /*
+        * zero out this buffer before freeing it to get rid of any stale
+        * BIOS image copied in memory.
+        */
+       memset(rbu_data.image_update_buffer, 0,
+               rbu_data.image_update_buffer_size);
+       if (rbu_data.dma_alloc == 1)
+               dma_free_coherent(NULL, rbu_data.bios_image_size,
+                       rbu_data.image_update_buffer, dell_rbu_dmaaddr);
+       else
+               free_pages((unsigned long) rbu_data.image_update_buffer,
+                       rbu_data.image_update_ordernum);
+
+       /*
+        * Re-initialize the rbu_data variables after a free
+        */
+       rbu_data.image_update_ordernum = -1;
+       rbu_data.image_update_buffer = NULL;
+       rbu_data.image_update_buffer_size = 0;
+       rbu_data.bios_image_size = 0;
+       rbu_data.dma_alloc = 0;
+}
+
+/*
+ * img_update_realloc: This function allocates the contiguous pages to
+ * accommodate the requested size of data. The memory address and size
+ * values are stored globally and on every call to this function the new
+ * size is checked to see if more data is required than the existing size.
+ * If true the previous memory is freed and new allocation is done to
+ * accommodate the new size. If the incoming size is less then than the
+ * already allocated size, then that memory is reused. This function is
+ * called with lock held and returns with lock held.
+ */
+static int img_update_realloc(unsigned long size)
+{
+       unsigned char *image_update_buffer = NULL;
+       unsigned long rc;
+       unsigned long img_buf_phys_addr;
+       int ordernum;
+       int dma_alloc = 0;
+
+       /*
+        * check if the buffer of sufficient size has been
+        * already allocated
+        */
+       if (rbu_data.image_update_buffer_size >= size) {
+               /*
+                * check for corruption
+                */
+               if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
+                       printk(KERN_ERR "dell_rbu:%s: corruption "
+                               "check failed\n", __func__);
+                       return -EINVAL;
+               }
+               /*
+                * we have a valid pre-allocated buffer with
+                * sufficient size
+                */
+               return 0;
+       }
+
+       /*
+        * free any previously allocated buffer
+        */
+       img_update_free();
+
+       spin_unlock(&rbu_data.lock);
+
+       ordernum = get_order(size);
+       image_update_buffer =
+               (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
+
+       img_buf_phys_addr =
+               (unsigned long) virt_to_phys(image_update_buffer);
+
+       if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
+               free_pages((unsigned long) image_update_buffer, ordernum);
+               ordernum = -1;
+               image_update_buffer = dma_alloc_coherent(NULL, size,
+                       &dell_rbu_dmaaddr, GFP_KERNEL);
+               dma_alloc = 1;
+       }
+
+       spin_lock(&rbu_data.lock);
+
+       if (image_update_buffer != NULL) {
+               rbu_data.image_update_buffer = image_update_buffer;
+               rbu_data.image_update_buffer_size = size;
+               rbu_data.bios_image_size =
+                       rbu_data.image_update_buffer_size;
+               rbu_data.image_update_ordernum = ordernum;
+               rbu_data.dma_alloc = dma_alloc;
+               rc = 0;
+       } else {
+               pr_debug("Not enough memory for image update:"
+                       "size = %ld\n", size);
+               rc = -ENOMEM;
+       }
+
+       return rc;
+}
+
+static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
+{
+       int retval;
+       size_t bytes_left;
+       size_t data_length;
+       char *ptempBuf = buffer;
+
+       /* check to see if we have something to return */
+       if (rbu_data.num_packets == 0) {
+               pr_debug("read_packet_data: no packets written\n");
+               retval = -ENOMEM;
+               goto read_rbu_data_exit;
+       }
+
+       if (pos > rbu_data.imagesize) {
+               retval = 0;
+               printk(KERN_WARNING "dell_rbu:read_packet_data: "
+                       "data underrun\n");
+               goto read_rbu_data_exit;
+       }
+
+       bytes_left = rbu_data.imagesize - pos;
+       data_length = min(bytes_left, count);
+
+       if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
+               goto read_rbu_data_exit;
+
+       if ((pos + count) > rbu_data.imagesize) {
+               rbu_data.packet_read_count = 0;
+               /* this was the last copy */
+               retval = bytes_left;
+       } else
+               retval = count;
+
+      read_rbu_data_exit:
+       return retval;
+}
+
+static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
+{
+       /* check to see if we have something to return */
+       if ((rbu_data.image_update_buffer == NULL) ||
+               (rbu_data.bios_image_size == 0)) {
+               pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
+                       "bios_image_size %lu\n",
+                       rbu_data.image_update_buffer,
+                       rbu_data.bios_image_size);
+               return -ENOMEM;
+       }
+
+       return memory_read_from_buffer(buffer, count, &pos,
+                       rbu_data.image_update_buffer, rbu_data.bios_image_size);
+}
+
+static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj,
+                            struct bin_attribute *bin_attr,
+                            char *buffer, loff_t pos, size_t count)
+{
+       ssize_t ret_count = 0;
+
+       spin_lock(&rbu_data.lock);
+
+       if (!strcmp(image_type, "mono"))
+               ret_count = read_rbu_mono_data(buffer, pos, count);
+       else if (!strcmp(image_type, "packet"))
+               ret_count = read_packet_data(buffer, pos, count);
+       else
+               pr_debug("read_rbu_data: invalid image type specified\n");
+
+       spin_unlock(&rbu_data.lock);
+       return ret_count;
+}
+
+static void callbackfn_rbu(const struct firmware *fw, void *context)
+{
+       rbu_data.entry_created = 0;
+
+       if (!fw)
+               return;
+
+       if (!fw->size)
+               goto out;
+
+       spin_lock(&rbu_data.lock);
+       if (!strcmp(image_type, "mono")) {
+               if (!img_update_realloc(fw->size))
+                       memcpy(rbu_data.image_update_buffer,
+                               fw->data, fw->size);
+       } else if (!strcmp(image_type, "packet")) {
+               /*
+                * we need to free previous packets if a
+                * new hunk of packets needs to be downloaded
+                */
+               packet_empty_list();
+               if (packetize_data(fw->data, fw->size))
+                       /* Incase something goes wrong when we are
+                        * in middle of packetizing the data, we
+                        * need to free up whatever packets might
+                        * have been created before we quit.
+                        */
+                       packet_empty_list();
+       } else
+               pr_debug("invalid image type specified.\n");
+       spin_unlock(&rbu_data.lock);
+ out:
+       release_firmware(fw);
+}
+
+static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj,
+                                  struct bin_attribute *bin_attr,
+                                  char *buffer, loff_t pos, size_t count)
+{
+       int size = 0;
+       if (!pos)
+               size = scnprintf(buffer, count, "%s\n", image_type);
+       return size;
+}
+
+static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj,
+                                   struct bin_attribute *bin_attr,
+                                   char *buffer, loff_t pos, size_t count)
+{
+       int rc = count;
+       int req_firm_rc = 0;
+       int i;
+       spin_lock(&rbu_data.lock);
+       /*
+        * Find the first newline or space
+        */
+       for (i = 0; i < count; ++i)
+               if (buffer[i] == '\n' || buffer[i] == ' ') {
+                       buffer[i] = '\0';
+                       break;
+               }
+       if (i == count)
+               buffer[count] = '\0';
+
+       if (strstr(buffer, "mono"))
+               strcpy(image_type, "mono");
+       else if (strstr(buffer, "packet"))
+               strcpy(image_type, "packet");
+       else if (strstr(buffer, "init")) {
+               /*
+                * If due to the user error the driver gets in a bad
+                * state where even though it is loaded , the
+                * /sys/class/firmware/dell_rbu entries are missing.
+                * to cover this situation the user can recreate entries
+                * by writing init to image_type.
+                */
+               if (!rbu_data.entry_created) {
+                       spin_unlock(&rbu_data.lock);
+                       req_firm_rc = request_firmware_nowait(THIS_MODULE,
+                               FW_ACTION_NOHOTPLUG, "dell_rbu",
+                               &rbu_device->dev, GFP_KERNEL, &context,
+                               callbackfn_rbu);
+                       if (req_firm_rc) {
+                               printk(KERN_ERR
+                                       "dell_rbu:%s request_firmware_nowait"
+                                       " failed %d\n", __func__, rc);
+                               rc = -EIO;
+                       } else
+                               rbu_data.entry_created = 1;
+
+                       spin_lock(&rbu_data.lock);
+               }
+       } else {
+               printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
+               spin_unlock(&rbu_data.lock);
+               return -EINVAL;
+       }
+
+       /* we must free all previous allocations */
+       packet_empty_list();
+       img_update_free();
+       spin_unlock(&rbu_data.lock);
+
+       return rc;
+}
+
+static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj,
+                                   struct bin_attribute *bin_attr,
+                                   char *buffer, loff_t pos, size_t count)
+{
+       int size = 0;
+       if (!pos) {
+               spin_lock(&rbu_data.lock);
+               size = scnprintf(buffer, count, "%lu\n", rbu_data.packetsize);
+               spin_unlock(&rbu_data.lock);
+       }
+       return size;
+}
+
+static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj,
+                                    struct bin_attribute *bin_attr,
+                                    char *buffer, loff_t pos, size_t count)
+{
+       unsigned long temp;
+       spin_lock(&rbu_data.lock);
+       packet_empty_list();
+       sscanf(buffer, "%lu", &temp);
+       if (temp < 0xffffffff)
+               rbu_data.packetsize = temp;
+
+       spin_unlock(&rbu_data.lock);
+       return count;
+}
+
+static struct bin_attribute rbu_data_attr = {
+       .attr = {.name = "data", .mode = 0444},
+       .read = read_rbu_data,
+};
+
+static struct bin_attribute rbu_image_type_attr = {
+       .attr = {.name = "image_type", .mode = 0644},
+       .read = read_rbu_image_type,
+       .write = write_rbu_image_type,
+};
+
+static struct bin_attribute rbu_packet_size_attr = {
+       .attr = {.name = "packet_size", .mode = 0644},
+       .read = read_rbu_packet_size,
+       .write = write_rbu_packet_size,
+};
+
+static int __init dcdrbu_init(void)
+{
+       int rc;
+       spin_lock_init(&rbu_data.lock);
+
+       init_packet_head();
+       rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0);
+       if (IS_ERR(rbu_device)) {
+               printk(KERN_ERR
+                       "dell_rbu:%s:platform_device_register_simple "
+                       "failed\n", __func__);
+               return PTR_ERR(rbu_device);
+       }
+
+       rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+       if (rc)
+               goto out_devreg;
+       rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+       if (rc)
+               goto out_data;
+       rc = sysfs_create_bin_file(&rbu_device->dev.kobj,
+               &rbu_packet_size_attr);
+       if (rc)
+               goto out_imtype;
+
+       rbu_data.entry_created = 0;
+       return 0;
+
+out_imtype:
+       sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
+out_data:
+       sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
+out_devreg:
+       platform_device_unregister(rbu_device);
+       return rc;
+}
+
+static __exit void dcdrbu_exit(void)
+{
+       spin_lock(&rbu_data.lock);
+       packet_empty_list();
+       img_update_free();
+       spin_unlock(&rbu_data.lock);
+       platform_device_unregister(rbu_device);
+}
+
+module_exit(dcdrbu_exit);
+module_init(dcdrbu_init);
+
+/* vim:noet:ts=8:sw=8
+*/
index d4f1259ff5a233bc22bb0700ddb354ace4b40e58..b6489cba29853e1919cd21c36e7fd19f3c720748 100644 (file)
@@ -212,7 +212,7 @@ static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
                        return 0;
                }
        }
-       pr_err("timeout in read_ec_cmd\n");
+       pr_err("timeout in %s\n", __func__);
        return -1;
 }
 
@@ -1146,6 +1146,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBM"),
                },
        },
+       {
+               .ident = "Lenovo Legion Y530-15ICH",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion Y530-15ICH"),
+               },
+       },
        {
                .ident = "Lenovo Legion Y720-15IKB",
                .matches = {
index 6cf9b7fa5bf0486fcf7e9d0b3ed805cfe07ca19d..e28bcf61b12698c6bf88668fe542e49cca463d32 100644 (file)
@@ -1,19 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Intel HID event & 5 button array driver
  *
  *  Copyright (C) 2015 Alex Hung <alex.hung@canonical.com>
  *  Copyright (C) 2015 Andrew Lutomirski <luto@kernel.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
  */
 
 #include <linux/acpi.h>
index 7344d841f4d98d17810b5f6bdbee8965415af6e5..3b81cb896fedff37c231ed62de5c9d859a2df3ac 100644 (file)
@@ -1,26 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Copyright 2013 Matthew Garrett <mjg59@srcf.ucam.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-
-#include <linux/init.h>
+#include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/acpi.h>
 
 MODULE_LICENSE("GPL");
 
@@ -53,12 +38,10 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
        acpi = to_acpi_device(dev);
 
        error = kstrtoul(buf, 0, &value);
-
        if (error)
                return error;
 
        status = acpi_execute_simple_method(acpi->handle, "SFFS", value);
-
        if (ACPI_FAILURE(status))
                return -EINVAL;
 
@@ -99,12 +82,10 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
        acpi = to_acpi_device(dev);
 
        error = kstrtoul(buf, 0, &value);
-
        if (error)
                return error;
 
        status = acpi_execute_simple_method(acpi->handle, "SFTV", value);
-
        if (ACPI_FAILURE(status))
                return -EINVAL;
 
index bbe4c06c769f66eabf8ed956cbb3361ef8407220..64c2dc93472f474869b98e418ac1a67bb74d5559 100644 (file)
@@ -1,25 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *  Copyright 2013 Matthew Garrett <mjg59@srcf.ucam.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-
-#include <linux/init.h>
-#include <linux/module.h>
 #include <linux/acpi.h>
+#include <linux/module.h>
 
 MODULE_LICENSE("GPL");
 
@@ -44,6 +29,7 @@ static const struct acpi_device_id smartconnect_ids[] = {
        {"INT33A0", 0},
        {"", 0}
 };
+MODULE_DEVICE_TABLE(acpi, smartconnect_ids);
 
 static struct acpi_driver smartconnect_driver = {
        .owner = THIS_MODULE,
@@ -56,5 +42,3 @@ static struct acpi_driver smartconnect_driver = {
 };
 
 module_acpi_driver(smartconnect_driver);
-
-MODULE_DEVICE_TABLE(acpi, smartconnect_ids);
index c2257bd06f1863d848fc384b2ac5577294bef8f5..9ded8e2af312f23293a5a6a8a56a3c7b8d499c3e 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * WMI Thunderbolt driver
  *
  * Copyright (C) 2017 Dell Inc. All Rights Reserved.
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -38,12 +30,16 @@ static ssize_t force_power_store(struct device *dev,
        input.length = sizeof(u8);
        input.pointer = &mode;
        mode = hex_to_bin(buf[0]);
+       dev_dbg(dev, "force_power: storing %#x\n", mode);
        if (mode == 0 || mode == 1) {
                status = wmi_evaluate_method(INTEL_WMI_THUNDERBOLT_GUID, 0, 1,
                                             &input, NULL);
-               if (ACPI_FAILURE(status))
+               if (ACPI_FAILURE(status)) {
+                       dev_dbg(dev, "force_power: failed to evaluate ACPI method\n");
                        return -ENODEV;
+               }
        } else {
+               dev_dbg(dev, "force_power: unsupported mode\n");
                return -EINVAL;
        }
        return count;
@@ -95,4 +91,4 @@ module_wmi_driver(intel_wmi_thunderbolt_driver);
 MODULE_ALIAS("wmi:" INTEL_WMI_THUNDERBOLT_GUID);
 MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
 MODULE_DESCRIPTION("Intel WMI Thunderbolt force power driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/intel_atomisp2_pm.c b/drivers/platform/x86/intel_atomisp2_pm.c
new file mode 100644 (file)
index 0000000..9371603
--- /dev/null
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Dummy driver for Intel's Image Signal Processor found on Bay and Cherry
+ * Trail devices. The sole purpose of this driver is to allow the ISP to
+ * be put in D3.
+ *
+ * Copyright (C) 2018 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on various non upstream patches for ISP support:
+ * Copyright (C) 2010-2017 Intel Corporation. All rights reserved.
+ * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <asm/iosf_mbi.h>
+
+/* PCI configuration regs */
+#define PCI_INTERRUPT_CTRL             0x9c
+
+#define PCI_CSI_CONTROL                        0xe8
+#define PCI_CSI_CONTROL_PORTS_OFF_MASK 0x7
+
+/* IOSF BT_MBI_UNIT_PMC regs */
+#define ISPSSPM0                       0x39
+#define ISPSSPM0_ISPSSC_OFFSET         0
+#define ISPSSPM0_ISPSSC_MASK           0x00000003
+#define ISPSSPM0_ISPSSS_OFFSET         24
+#define ISPSSPM0_ISPSSS_MASK           0x03000000
+#define ISPSSPM0_IUNIT_POWER_ON                0x0
+#define ISPSSPM0_IUNIT_POWER_OFF       0x3
+
+static int isp_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       unsigned long timeout;
+       u32 val;
+
+       pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, 0);
+
+       /*
+        * MRFLD IUNIT DPHY is located in an always-power-on island
+        * MRFLD HW design need all CSI ports are disabled before
+        * powering down the IUNIT.
+        */
+       pci_read_config_dword(dev, PCI_CSI_CONTROL, &val);
+       val |= PCI_CSI_CONTROL_PORTS_OFF_MASK;
+       pci_write_config_dword(dev, PCI_CSI_CONTROL, val);
+
+       /* Write 0x3 to ISPSSPM0 bit[1:0] to power off the IUNIT */
+       iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0,
+                       ISPSSPM0_IUNIT_POWER_OFF, ISPSSPM0_ISPSSC_MASK);
+
+       /*
+        * There should be no IUNIT access while power-down is
+        * in progress HW sighting: 4567865
+        * Wait up to 50 ms for the IUNIT to shut down.
+        */
+       timeout = jiffies + msecs_to_jiffies(50);
+       while (1) {
+               /* Wait until ISPSSPM0 bit[25:24] shows 0x3 */
+               iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM0, &val);
+               val = (val & ISPSSPM0_ISPSSS_MASK) >> ISPSSPM0_ISPSSS_OFFSET;
+               if (val == ISPSSPM0_IUNIT_POWER_OFF)
+                       break;
+
+               if (time_after(jiffies, timeout)) {
+                       dev_err(&dev->dev, "IUNIT power-off timeout.\n");
+                       return -EBUSY;
+               }
+               usleep_range(1000, 2000);
+       }
+
+       pm_runtime_allow(&dev->dev);
+       pm_runtime_put_sync_suspend(&dev->dev);
+
+       return 0;
+}
+
+static void isp_remove(struct pci_dev *dev)
+{
+       pm_runtime_get_sync(&dev->dev);
+       pm_runtime_forbid(&dev->dev);
+}
+
+static int isp_pci_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int isp_pci_resume(struct device *dev)
+{
+       return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(isp_pm_ops, isp_pci_suspend,
+                           isp_pci_resume, NULL);
+
+static const struct pci_device_id isp_id_table[] = {
+       { PCI_VDEVICE(INTEL, 0x22b8), },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, isp_id_table);
+
+static struct pci_driver isp_pci_driver = {
+       .name = "intel_atomisp2_pm",
+       .id_table = isp_id_table,
+       .probe = isp_probe,
+       .remove = isp_remove,
+       .driver.pm = &isp_pm_ops,
+};
+
+module_pci_driver(isp_pci_driver);
+
+MODULE_DESCRIPTION("Intel AtomISP2 dummy / power-management drv (for suspend)");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL v2");
index 227943a20212cca12188cc18730bc42d6807da4e..951c105bafc1b8b1fc276ee04274690fd5f15f30 100644 (file)
@@ -1,21 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_bxtwc_tmu.c - Intel BXT Whiskey Cove PMIC TMU driver
+ * Intel BXT Whiskey Cove PMIC TMU driver
  *
  * Copyright (C) 2016 Intel Corporation. All rights reserved.
  *
  * This driver adds TMU (Time Management Unit) support for Intel BXT platform.
  * It enables the alarm wake-up functionality in the TMU unit of Whiskey Cove
  * PMIC.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
 #include <linux/module.h>
index f40b1c1921064b734614705c72dc212700f979fc..464fe93657b53e03268eabb2f41f5cdd0583d96e 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Cherry Trail ACPI INT33FE pseudo device driver
  *
  * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Some Intel Cherry Trail based device which ship with Windows 10, have
  * this weird INT33FE ACPI device with a CRS table with 4 I2cSerialBusV2
  * resources, for 4 different chips attached to various i2c busses:
@@ -257,4 +254,4 @@ module_platform_driver(cht_int33fe_driver);
 
 MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE pseudo device driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index 38b8e7cfe88c06a68fa351b7048247324fc89e31..0df2e82dd24924bd6d92ff74f2434b4eb1f30d64 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Power-button driver for Dollar Cove TI PMIC
  * Copyright (C) 2014 Intel Corp
index e89ad4964dc139daec390560bfcecb145cdd5505..4b8f7305fc8a773b8a0e06291b69672ef559a7ab 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel INT0002 "Virtual GPIO" driver
  *
@@ -9,10 +10,6 @@
  *
  * Author: Dyut Kumar Sil <dyut.k.sil@intel.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Some peripherals on Bay Trail and Cherry Trail platforms signal a Power
  * Management Event (PME) to the Power Management Controller (PMC) to wakeup
  * the system. When this happens software needs to clear the PME bus 0 status
 #define ICPU(model)    { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
 
 static const struct x86_cpu_id int0002_cpu_ids[] = {
-/*
- * Limit ourselves to Cherry Trail for now, until testing shows we
- * need to handle the INT0002 device on Baytrail too.
- *     ICPU(INTEL_FAM6_ATOM_SILVERMONT),        * Valleyview, Bay Trail *
- */
+       ICPU(INTEL_FAM6_ATOM_SILVERMONT),       /* Valleyview, Bay Trail  */
        ICPU(INTEL_FAM6_ATOM_AIRMONT),          /* Braswell, Cherry Trail */
        {}
 };
@@ -110,6 +103,21 @@ static void int0002_irq_mask(struct irq_data *data)
        outl(gpe_en_reg, GPE0A_EN_PORT);
 }
 
+static int int0002_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+       struct platform_device *pdev = to_platform_device(chip->parent);
+       int irq = platform_get_irq(pdev, 0);
+
+       /* Propagate to parent irq */
+       if (on)
+               enable_irq_wake(irq);
+       else
+               disable_irq_wake(irq);
+
+       return 0;
+}
+
 static irqreturn_t int0002_irq(int irq, void *data)
 {
        struct gpio_chip *chip = data;
@@ -132,6 +140,7 @@ static struct irq_chip int0002_irqchip = {
        .irq_ack                = int0002_irq_ack,
        .irq_mask               = int0002_irq_mask,
        .irq_unmask             = int0002_irq_unmask,
+       .irq_set_wake           = int0002_irq_set_wake,
 };
 
 static int int0002_probe(struct platform_device *pdev)
@@ -216,4 +225,4 @@ module_platform_driver(int0002_driver);
 
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("Intel INT0002 Virtual GPIO driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index c5ece7ef08c6df36b2d1ccff788f99c3cb408abe..225638a1b09e45d762668615cc9de93a0db100ba 100644 (file)
@@ -1,18 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2009-2010 Intel Corporation
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
- *
  * Authors:
  *     Jesse Barnes <jbarnes@virtuousgeek.org>
  */
@@ -1697,6 +1686,6 @@ static struct pci_driver ips_pci_driver = {
 
 module_pci_driver(ips_pci_driver);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Jesse Barnes <jbarnes@virtuousgeek.org>");
 MODULE_DESCRIPTION("Intelligent Power Sharing Driver");
index 60f4e3ddbe9f5b3f84e02030a57b98793141e615..512ad234ad0d67fccdb05d241d37fd887da164d5 100644 (file)
@@ -1,17 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2010 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * The full GNU General Public License is included in this distribution in
- * the file called "COPYING".
  */
 
 void ips_link_to_i915_driver(void);
index ef9b0af8cdd36a6adc68fb2f3b835993bfa46ebe..77eb8709c931c03dbeda565b71c65e8d6f1d564e 100644 (file)
@@ -1,25 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- *  intel_menlow.c - Intel menlow Driver for thermal management extension
+ *  Intel menlow Driver for thermal management extension
  *
  *  Copyright (C) 2008 Intel Corp
  *  Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
  *  Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  *  This driver creates the sys I/F for programming the sensors.
  *  It also implements the driver for intel menlow memory controller (hardware
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/acpi.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/pm.h>
+#include <linux/slab.h>
 #include <linux/thermal.h>
-#include <linux/acpi.h>
+#include <linux/types.h>
 
 MODULE_AUTHOR("Thomas Sujith");
 MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Intel Menlow platform specific driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 
 /*
  * Memory controller device control
index 5ad44204a9c3c997bf237aacfb1bbb99ab292ef7..292bace83f1e3d95a8dae813370b1fc6610bc0df 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Power button driver for Intel MID platforms.
  *
@@ -5,18 +6,8 @@
  *
  * Author: Hong Liu <hong.liu@intel.com>
  * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
  */
 
-#include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/intel_msic.h>
@@ -121,12 +112,9 @@ static const struct mid_pb_ddata mrfld_ddata = {
        .setup  = mrfld_setup,
 };
 
-#define ICPU(model, ddata)     \
-       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (kernel_ulong_t)&ddata }
-
 static const struct x86_cpu_id mid_pb_cpu_ids[] = {
-       ICPU(INTEL_FAM6_ATOM_SALTWELL_MID,              mfld_ddata),
-       ICPU(INTEL_FAM6_ATOM_SILVERMONT_MID,    mrfld_ddata),
+       INTEL_CPU_FAM6(ATOM_SALTWELL_MID,       mfld_ddata),
+       INTEL_CPU_FAM6(ATOM_SILVERMONT_MID,     mrfld_ddata),
        {}
 };
 
index 008a76903cbfb62221ac4fd4bb8aaa7b46c56fb1..f402e2e74a38392e9abf1eae8debc3630dcc828c 100644 (file)
@@ -1,39 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_mid_thermal.c - Intel MID platform thermal driver
+ * Intel MID platform thermal driver
  *
  * Copyright (C) 2011 Intel Corporation
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  * Author: Durgadoss R <durgadoss.r@intel.com>
  */
 
 #define pr_fmt(fmt) "intel_mid_thermal: " fmt
 
-#include <linux/module.h>
-#include <linux/init.h>
+#include <linux/device.h>
 #include <linux/err.h>
+#include <linux/mfd/intel_msic.h>
+#include <linux/module.h>
 #include <linux/param.h>
-#include <linux/device.h>
 #include <linux/platform_device.h>
-#include <linux/slab.h>
 #include <linux/pm.h>
+#include <linux/slab.h>
 #include <linux/thermal.h>
-#include <linux/mfd/intel_msic.h>
 
 /* Number of thermal sensors */
 #define MSIC_THERMAL_SENSORS   4
@@ -567,4 +551,4 @@ module_platform_driver(mid_thermal_driver);
 
 MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
 MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index 5747f63c8d9f490c51edb31f5fc836ee89dab33f..3c0438ba385ee8494c14a4d24147201e04dcaee6 100644 (file)
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
- * intel_oaktrail.c - Intel OakTrail Platform support.
+ * Intel OakTrail Platform support
  *
  * Copyright (C) 2010-2011 Intel Corporation
  * Author: Yin Kangkai (kangkai.yin@intel.com)
@@ -8,21 +9,6 @@
  * <cezary.jackiewicz (at) gmail.com>, based on MSI driver
  * Copyright (C) 2006 Lennart Poettering <mzxreary (at) 0pointer (dot) de>
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- *
  * This driver does below things:
  * 1. registers itself in the Linux backlight control in
  *    /sys/class/backlight/intel_oaktrail/
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/acpi.h>
-#include <linux/fb.h>
-#include <linux/mutex.h>
+#include <linux/backlight.h>
+#include <linux/dmi.h>
 #include <linux/err.h>
+#include <linux/fb.h>
 #include <linux/i2c.h>
-#include <linux/backlight.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/platform_device.h>
-#include <linux/dmi.h>
 #include <linux/rfkill.h>
+
 #include <acpi/video.h>
 
 #define DRIVER_NAME    "intel_oaktrail"
index 2d272a3e017621365de7d38dfbfa68bef7d73ab2..6b31d410cb09abeb57aec266a7896c4dbbec1dc3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Core SoC Power Management Controller Driver
  *
@@ -6,16 +7,6 @@
  *
  * Authors: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
  *          Vishwanath Somayaji <vishwanath.somayaji@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 93a7e99e1f8b8a0a8d241416c1540cc66c779f20..be045348ad86b2674c3b08b3c1af54b3844ea339 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Core SoC Power Management Controller Header File
  *
@@ -6,16 +7,6 @@
  *
  * Authors: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
  *          Vishwanath Somayaji <vishwanath.somayaji@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */
 
 #ifndef PMC_CORE_H
index e7edc8c6393674dfdcfcf53cccb80da50fd255f2..7964ba22ef8d997d31e3cd83af9a56feb90dd088 100644 (file)
@@ -1,39 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_pmc_ipc.c: Driver for the Intel PMC IPC mechanism
+ * Driver for the Intel PMC IPC mechanism
  *
  * (C) Copyright 2014-2015 Intel Corporation
  *
- * This driver is based on Intel SCU IPC driver(intel_scu_opc.c) by
+ * This driver is based on Intel SCU IPC driver(intel_scu_ipc.c) by
  *     Sreedhara DS <sreedhara.ds@intel.com>
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- *
  * PMC running in ARC processor communicates with other entity running in IA
  * core through IPC mechanism which in turn messaging between IA core ad PMC.
  */
 
-#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/atomic.h>
+#include <linux/bitops.h>
 #include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
 #include <linux/device.h>
-#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
-#include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/pm_qos.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
 #include <linux/sched.h>
-#include <linux/atomic.h>
-#include <linux/notifier.h>
-#include <linux/suspend.h>
-#include <linux/acpi.h>
-#include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/spinlock.h>
+#include <linux/suspend.h>
 
 #include <asm/intel_pmc_ipc.h>
 
@@ -1029,7 +1024,7 @@ static void __exit intel_pmc_ipc_exit(void)
 
 MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>");
 MODULE_DESCRIPTION("Intel PMC IPC driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 
 /* Some modules are dependent on this, so init earlier */
 fs_initcall(intel_pmc_ipc_init);
index 2efeab650345c044371aa7c56624e4d650ea7c93..79671927f4ef6ada5833419c58a8aeb23fd1621f 100644 (file)
@@ -1,25 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Driver for the Intel P-Unit Mailbox IPC mechanism
  *
  * (C) Copyright 2015 Intel Corporation
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * The heart of the P-Unit is the Foxton microcontroller and its firmware,
  * which provide mailbox interface for power management usage.
  */
 
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
 #include <linux/acpi.h>
-#include <linux/delay.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
+
 #include <asm/intel_punit_ipc.h>
 
 /* IPC Mailbox registers */
index 75c8fef7a482c41717c69aa8ef98b21ef4dd1043..cdab916fbf92775320400d1879e112dfdc8e4034 100644 (file)
@@ -1,14 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_scu_ipc.c: Driver for the Intel SCU IPC mechanism
+ * Driver for the Intel SCU IPC mechanism
  *
  * (C) Copyright 2008-2010,2015 Intel Corporation
  * Author: Sreedhara DS (sreedhara.ds@intel.com)
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- *
  * SCU running in ARC processor communicates with other entity running in IA
  * core through IPC mechanism which in turn messaging between IA core ad SCU.
  * SCU has two IPC mechanism IPC-1 and IPC-2. IPC-1 is used between IA32 and
  * IPC-1 Driver provides an API for power control unit registers (e.g. MSIC)
  * along with other APIs.
  */
+
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/device.h>
-#include <linux/pm.h>
-#include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
 #include <linux/sfi.h>
+
 #include <asm/intel-mid.h>
 #include <asm/intel_scu_ipc.h>
 
index aa454241489c9f541864f34828e19318514d3560..8afe6fa06d7b8d45a1f9f68e5483f1e191f62e91 100644 (file)
@@ -1,32 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * intel_scu_ipc.c: Driver for the Intel SCU IPC mechanism
+ * Driver for the Intel SCU IPC mechanism
  *
  * (C) Copyright 2008-2010 Intel Corporation
  * Author: Sreedhara DS (sreedhara.ds@intel.com)
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- *
- * This driver provides ioctl interfaces to call intel scu ipc driver api
+ * This driver provides IOCTL interfaces to call Intel SCU IPC driver API.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/fs.h>
 #include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
 #include <asm/intel_scu_ipc.h>
 
 static int major;
 
-/* ioctl commnds */
+/* IOCTL commands */
 #define        INTE_SCU_IPC_REGISTER_READ      0
 #define INTE_SCU_IPC_REGISTER_WRITE    1
 #define INTE_SCU_IPC_REGISTER_UPDATE   2
index f378621b5fe9d86632a853a33599b1efff88b05a..d4040bb222b485ead8c8caa8a1b3c4463e72dffa 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel SoC Core Telemetry Driver
  * Copyright (C) 2015, Intel Corporation.
  * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  * Telemetry Framework provides platform related PM and performance statistics.
  * This file provides the core telemetry API implementation.
  */
@@ -460,4 +452,4 @@ module_exit(telemetry_module_exit);
 
 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 MODULE_DESCRIPTION("Intel SoC Telemetry Interface");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index cee08f23629245803783734af6229ac18c69e3e6..40bce560eb30d9cf2ca1a348d7b1eece30d00616 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel SOC Telemetry debugfs Driver: Currently supports APL
  * Copyright (c) 2015, Intel Corporation.
  * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  * This file provides the debugfs interfaces for telemetry.
  * /sys/kernel/debug/telemetry/pss_info: Shows Primary Control Sub-Sys Counters
  * /sys/kernel/debug/telemetry/ioss_info: Shows IO Sub-System Counters
@@ -72,9 +64,6 @@
 #define TELEM_IOSS_DX_D0IX_EVTS                25
 #define TELEM_IOSS_PG_EVTS             30
 
-#define TELEM_DEBUGFS_CPU(model, data) \
-       { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&data}
-
 #define TELEM_CHECK_AND_PARSE_EVTS(EVTID, EVTNUM, BUF, EVTLOG, EVTDAT, MASK) { \
        if (evtlog[index].telem_evtid == (EVTID)) { \
                for (idx = 0; idx < (EVTNUM); idx++) \
@@ -319,8 +308,8 @@ static struct telemetry_debugfs_conf telem_apl_debugfs_conf = {
 };
 
 static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = {
-       TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_debugfs_conf),
-       TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS, telem_apl_debugfs_conf),
+       INTEL_CPU_FAM6(ATOM_GOLDMONT, telem_apl_debugfs_conf),
+       INTEL_CPU_FAM6(ATOM_GOLDMONT_PLUS, telem_apl_debugfs_conf),
        {}
 };
 
@@ -951,12 +940,16 @@ static int __init telemetry_debugfs_init(void)
        debugfs_conf = (struct telemetry_debugfs_conf *)id->driver_data;
 
        err = telemetry_pltconfig_valid();
-       if (err < 0)
+       if (err < 0) {
+               pr_info("Invalid pltconfig, ensure IPC1 device is enabled in BIOS\n");
                return -ENODEV;
+       }
 
        err = telemetry_debugfs_check_evts();
-       if (err < 0)
+       if (err < 0) {
+               pr_info("telemetry_debugfs_check_evts failed\n");
                return -EINVAL;
+       }
 
        register_pm_notifier(&pm_notifier);
 
@@ -1037,4 +1030,4 @@ module_exit(telemetry_debugfs_exit);
 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 MODULE_DESCRIPTION("Intel SoC Telemetry debugfs Interface");
 MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index fcc6bee51a422a1c95e205f0d2874fc746ed09e2..df8565bad595c72ba7b889a7d50afe2e0e75d9c6 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel SOC Telemetry Platform Driver: Currently supports APL
  * Copyright (c) 2015, Intel Corporation.
  * All Rights Reserved.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  * This file provides the platform specific telemetry implementation for APL.
  * It used the PUNIT and PMC IPC interfaces for configuring the counters.
  * The accumulated results are fetched from SRAM.
@@ -1242,4 +1234,4 @@ module_exit(telemetry_module_exit);
 MODULE_AUTHOR("Souvik Kumar Chakravarty <souvik.k.chakravarty@intel.com>");
 MODULE_DESCRIPTION("Intel SoC Telemetry Platform Driver");
 MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index a6d5aa0c3c479dbd7f345a3f5666ae0ef72e456d..7b9cc841ab6557157a71691cf131cd43cc7ecb9c 100644 (file)
@@ -1,28 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel Turbo Boost Max Technology 3.0 legacy (non HWP) enumeration driver
  * Copyright (c) 2017, Intel Corporation.
  * All rights reserved.
  *
  * Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <linux/kernel.h>
+#include <linux/cpufeature.h>
+#include <linux/cpuhotplug.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/topology.h>
 #include <linux/workqueue.h>
-#include <linux/cpuhotplug.h>
-#include <linux/cpufeature.h>
+
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 
diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c
new file mode 100644 (file)
index 0000000..c0bb1f8
--- /dev/null
@@ -0,0 +1,700 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * lg-laptop.c - LG Gram ACPI features and hotkeys Driver
+ *
+ * Copyright (C) 2018 Matan Ziv-Av <matan@svgalib.org>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/acpi.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#define LED_DEVICE(_name, max) struct led_classdev _name = { \
+       .name           = __stringify(_name),   \
+       .max_brightness = max,                  \
+       .brightness_set = _name##_set,          \
+       .brightness_get = _name##_get,          \
+}
+
+MODULE_AUTHOR("Matan Ziv-Av");
+MODULE_DESCRIPTION("LG WMI Hotkey Driver");
+MODULE_LICENSE("GPL");
+
+#define WMI_EVENT_GUID0        "E4FB94F9-7F2B-4173-AD1A-CD1D95086248"
+#define WMI_EVENT_GUID1        "023B133E-49D1-4E10-B313-698220140DC2"
+#define WMI_EVENT_GUID2        "37BE1AC0-C3F2-4B1F-BFBE-8FDEAF2814D6"
+#define WMI_EVENT_GUID3        "911BAD44-7DF8-4FBB-9319-BABA1C4B293B"
+#define WMI_METHOD_WMAB "C3A72B38-D3EF-42D3-8CBB-D5A57049F66D"
+#define WMI_METHOD_WMBB "2B4F501A-BD3C-4394-8DCF-00A7D2BC8210"
+#define WMI_EVENT_GUID  WMI_EVENT_GUID0
+
+#define WMAB_METHOD     "\\XINI.WMAB"
+#define WMBB_METHOD     "\\XINI.WMBB"
+#define SB_GGOV_METHOD  "\\_SB.GGOV"
+#define GOV_TLED        0x2020008
+#define WM_GET          1
+#define WM_SET          2
+#define WM_KEY_LIGHT    0x400
+#define WM_TLED         0x404
+#define WM_FN_LOCK      0x407
+#define WM_BATT_LIMIT   0x61
+#define WM_READER_MODE  0xBF
+#define WM_FAN_MODE    0x33
+#define WMBB_USB_CHARGE 0x10B
+#define WMBB_BATT_LIMIT 0x10C
+
+#define PLATFORM_NAME   "lg-laptop"
+
+MODULE_ALIAS("wmi:" WMI_EVENT_GUID0);
+MODULE_ALIAS("wmi:" WMI_EVENT_GUID1);
+MODULE_ALIAS("wmi:" WMI_EVENT_GUID2);
+MODULE_ALIAS("wmi:" WMI_EVENT_GUID3);
+MODULE_ALIAS("wmi:" WMI_METHOD_WMAB);
+MODULE_ALIAS("wmi:" WMI_METHOD_WMBB);
+MODULE_ALIAS("acpi*:LGEX0815:*");
+
+static struct platform_device *pf_device;
+static struct input_dev *wmi_input_dev;
+
+static u32 inited;
+#define INIT_INPUT_WMI_0        0x01
+#define INIT_INPUT_WMI_2        0x02
+#define INIT_INPUT_ACPI         0x04
+#define INIT_TPAD_LED           0x08
+#define INIT_KBD_LED            0x10
+#define INIT_SPARSE_KEYMAP        0x80
+
+static const struct key_entry wmi_keymap[] = {
+       {KE_KEY, 0x70, {KEY_F15} },      /* LG control panel (F1) */
+       {KE_KEY, 0x74, {KEY_F13} },      /* Touchpad toggle (F5) */
+       {KE_KEY, 0xf020000, {KEY_F14} }, /* Read mode (F9) */
+       {KE_KEY, 0x10000000, {KEY_F16} },/* Keyboard backlight (F8) - pressing
+                                         * this key both sends an event and
+                                         * changes backlight level.
+                                         */
+       {KE_KEY, 0x80, {KEY_RFKILL} },
+       {KE_END, 0}
+};
+
+static int ggov(u32 arg0)
+{
+       union acpi_object args[1];
+       union acpi_object *r;
+       acpi_status status;
+       acpi_handle handle;
+       struct acpi_object_list arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       int res;
+
+       args[0].type = ACPI_TYPE_INTEGER;
+       args[0].integer.value = arg0;
+
+       status = acpi_get_handle(NULL, (acpi_string) SB_GGOV_METHOD, &handle);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Cannot get handle");
+               return -ENODEV;
+       }
+
+       arg.count = 1;
+       arg.pointer = args;
+
+       status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_err(handle, "GGOV: call failed.\n");
+               return -EINVAL;
+       }
+
+       r = buffer.pointer;
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EINVAL;
+       }
+
+       res = r->integer.value;
+       kfree(r);
+
+       return res;
+}
+
+static union acpi_object *lg_wmab(u32 method, u32 arg1, u32 arg2)
+{
+       union acpi_object args[3];
+       acpi_status status;
+       acpi_handle handle;
+       struct acpi_object_list arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+       args[0].type = ACPI_TYPE_INTEGER;
+       args[0].integer.value = method;
+       args[1].type = ACPI_TYPE_INTEGER;
+       args[1].integer.value = arg1;
+       args[2].type = ACPI_TYPE_INTEGER;
+       args[2].integer.value = arg2;
+
+       status = acpi_get_handle(NULL, (acpi_string) WMAB_METHOD, &handle);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Cannot get handle");
+               return NULL;
+       }
+
+       arg.count = 3;
+       arg.pointer = args;
+
+       status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_err(handle, "WMAB: call failed.\n");
+               return NULL;
+       }
+
+       return buffer.pointer;
+}
+
+static union acpi_object *lg_wmbb(u32 method_id, u32 arg1, u32 arg2)
+{
+       union acpi_object args[3];
+       acpi_status status;
+       acpi_handle handle;
+       struct acpi_object_list arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       u8 buf[32];
+
+       *(u32 *)buf = method_id;
+       *(u32 *)(buf + 4) = arg1;
+       *(u32 *)(buf + 16) = arg2;
+       args[0].type = ACPI_TYPE_INTEGER;
+       args[0].integer.value = 0; /* ignored */
+       args[1].type = ACPI_TYPE_INTEGER;
+       args[1].integer.value = 1; /* Must be 1 or 2. Does not matter which */
+       args[2].type = ACPI_TYPE_BUFFER;
+       args[2].buffer.length = 32;
+       args[2].buffer.pointer = buf;
+
+       status = acpi_get_handle(NULL, (acpi_string)WMBB_METHOD, &handle);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Cannot get handle");
+               return NULL;
+       }
+
+       arg.count = 3;
+       arg.pointer = args;
+
+       status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_err(handle, "WMAB: call failed.\n");
+               return NULL;
+       }
+
+       return (union acpi_object *)buffer.pointer;
+}
+
+static void wmi_notify(u32 value, void *context)
+{
+       struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+       long data = (long)context;
+
+       pr_debug("event guid %li\n", data);
+       status = wmi_get_event_data(value, &response);
+       if (ACPI_FAILURE(status)) {
+               pr_err("Bad event status 0x%x\n", status);
+               return;
+       }
+
+       obj = (union acpi_object *)response.pointer;
+       if (!obj)
+               return;
+
+       if (obj->type == ACPI_TYPE_INTEGER) {
+               int eventcode = obj->integer.value;
+               struct key_entry *key;
+
+               key =
+                   sparse_keymap_entry_from_scancode(wmi_input_dev, eventcode);
+               if (key && key->type == KE_KEY)
+                       sparse_keymap_report_entry(wmi_input_dev, key, 1, true);
+       }
+
+       pr_debug("Type: %i    Eventcode: 0x%llx\n", obj->type,
+                obj->integer.value);
+       kfree(response.pointer);
+}
+
+static void wmi_input_setup(void)
+{
+       acpi_status status;
+
+       wmi_input_dev = input_allocate_device();
+       if (wmi_input_dev) {
+               wmi_input_dev->name = "LG WMI hotkeys";
+               wmi_input_dev->phys = "wmi/input0";
+               wmi_input_dev->id.bustype = BUS_HOST;
+
+               if (sparse_keymap_setup(wmi_input_dev, wmi_keymap, NULL) ||
+                   input_register_device(wmi_input_dev)) {
+                       pr_info("Cannot initialize input device");
+                       input_free_device(wmi_input_dev);
+                       return;
+               }
+
+               inited |= INIT_SPARSE_KEYMAP;
+               status = wmi_install_notify_handler(WMI_EVENT_GUID0, wmi_notify,
+                                                   (void *)0);
+               if (ACPI_SUCCESS(status))
+                       inited |= INIT_INPUT_WMI_0;
+
+               status = wmi_install_notify_handler(WMI_EVENT_GUID2, wmi_notify,
+                                                   (void *)2);
+               if (ACPI_SUCCESS(status))
+                       inited |= INIT_INPUT_WMI_2;
+       } else {
+               pr_info("Cannot allocate input device");
+       }
+}
+
+static void acpi_notify(struct acpi_device *device, u32 event)
+{
+       struct key_entry *key;
+
+       acpi_handle_debug(device->handle, "notify: %d\n", event);
+       if (inited & INIT_SPARSE_KEYMAP) {
+               key = sparse_keymap_entry_from_scancode(wmi_input_dev, 0x80);
+               if (key && key->type == KE_KEY)
+                       sparse_keymap_report_entry(wmi_input_dev, key, 1, true);
+       }
+}
+
+static ssize_t fan_mode_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buffer, size_t count)
+{
+       bool value;
+       union acpi_object *r;
+       u32 m;
+       int ret;
+
+       ret = kstrtobool(buffer, &value);
+       if (ret)
+               return ret;
+
+       r = lg_wmab(WM_FAN_MODE, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       m = r->integer.value;
+       kfree(r);
+       r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4));
+       kfree(r);
+       r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value);
+       kfree(r);
+
+       return count;
+}
+
+static ssize_t fan_mode_show(struct device *dev,
+                            struct device_attribute *attr, char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmab(WM_FAN_MODE, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = r->integer.value & 0x01;
+       kfree(r);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t usb_charge_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buffer, size_t count)
+{
+       bool value;
+       union acpi_object *r;
+       int ret;
+
+       ret = kstrtobool(buffer, &value);
+       if (ret)
+               return ret;
+
+       r = lg_wmbb(WMBB_USB_CHARGE, WM_SET, value);
+       if (!r)
+               return -EIO;
+
+       kfree(r);
+       return count;
+}
+
+static ssize_t usb_charge_show(struct device *dev,
+                              struct device_attribute *attr, char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmbb(WMBB_USB_CHARGE, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_BUFFER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = !!r->buffer.pointer[0x10];
+
+       kfree(r);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t reader_mode_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buffer, size_t count)
+{
+       bool value;
+       union acpi_object *r;
+       int ret;
+
+       ret = kstrtobool(buffer, &value);
+       if (ret)
+               return ret;
+
+       r = lg_wmab(WM_READER_MODE, WM_SET, value);
+       if (!r)
+               return -EIO;
+
+       kfree(r);
+       return count;
+}
+
+static ssize_t reader_mode_show(struct device *dev,
+                               struct device_attribute *attr, char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmab(WM_READER_MODE, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = !!r->integer.value;
+
+       kfree(r);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t fn_lock_store(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buffer, size_t count)
+{
+       bool value;
+       union acpi_object *r;
+       int ret;
+
+       ret = kstrtobool(buffer, &value);
+       if (ret)
+               return ret;
+
+       r = lg_wmab(WM_FN_LOCK, WM_SET, value);
+       if (!r)
+               return -EIO;
+
+       kfree(r);
+       return count;
+}
+
+static ssize_t fn_lock_show(struct device *dev,
+                           struct device_attribute *attr, char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmab(WM_FN_LOCK, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_BUFFER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = !!r->buffer.pointer[0];
+       kfree(r);
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t battery_care_limit_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buffer, size_t count)
+{
+       unsigned long value;
+       int ret;
+
+       ret = kstrtoul(buffer, 10, &value);
+       if (ret)
+               return ret;
+
+       if (value == 100 || value == 80) {
+               union acpi_object *r;
+
+               r = lg_wmab(WM_BATT_LIMIT, WM_SET, value);
+               if (!r)
+                       return -EIO;
+
+               kfree(r);
+               return count;
+       }
+
+       return -EINVAL;
+}
+
+static ssize_t battery_care_limit_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buffer)
+{
+       unsigned int status;
+       union acpi_object *r;
+
+       r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0);
+       if (!r)
+               return -EIO;
+
+       if (r->type != ACPI_TYPE_INTEGER) {
+               kfree(r);
+               return -EIO;
+       }
+
+       status = r->integer.value;
+       kfree(r);
+       if (status != 80 && status != 100)
+               status = 0;
+
+       return snprintf(buffer, PAGE_SIZE, "%d\n", status);
+}
+
+static DEVICE_ATTR_RW(fan_mode);
+static DEVICE_ATTR_RW(usb_charge);
+static DEVICE_ATTR_RW(reader_mode);
+static DEVICE_ATTR_RW(fn_lock);
+static DEVICE_ATTR_RW(battery_care_limit);
+
+static struct attribute *dev_attributes[] = {
+       &dev_attr_fan_mode.attr,
+       &dev_attr_usb_charge.attr,
+       &dev_attr_reader_mode.attr,
+       &dev_attr_fn_lock.attr,
+       &dev_attr_battery_care_limit.attr,
+       NULL
+};
+
+static const struct attribute_group dev_attribute_group = {
+       .attrs = dev_attributes,
+};
+
+static void tpad_led_set(struct led_classdev *cdev,
+                        enum led_brightness brightness)
+{
+       union acpi_object *r;
+
+       r = lg_wmab(WM_TLED, WM_SET, brightness > LED_OFF);
+       kfree(r);
+}
+
+static enum led_brightness tpad_led_get(struct led_classdev *cdev)
+{
+       return ggov(GOV_TLED) > 0 ? LED_ON : LED_OFF;
+}
+
+static LED_DEVICE(tpad_led, 1);
+
+static void kbd_backlight_set(struct led_classdev *cdev,
+                             enum led_brightness brightness)
+{
+       u32 val;
+       union acpi_object *r;
+
+       val = 0x22;
+       if (brightness <= LED_OFF)
+               val = 0;
+       if (brightness >= LED_FULL)
+               val = 0x24;
+       r = lg_wmab(WM_KEY_LIGHT, WM_SET, val);
+       kfree(r);
+}
+
+static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
+{
+       union acpi_object *r;
+       int val;
+
+       r = lg_wmab(WM_KEY_LIGHT, WM_GET, 0);
+
+       if (!r)
+               return LED_OFF;
+
+       if (r->type != ACPI_TYPE_BUFFER || r->buffer.pointer[1] != 0x05) {
+               kfree(r);
+               return LED_OFF;
+       }
+
+       switch (r->buffer.pointer[0] & 0x27) {
+       case 0x24:
+               val = LED_FULL;
+               break;
+       case 0x22:
+               val = LED_HALF;
+               break;
+       default:
+               val = LED_OFF;
+       }
+
+       kfree(r);
+
+       return val;
+}
+
+static LED_DEVICE(kbd_backlight, 255);
+
+static void wmi_input_destroy(void)
+{
+       if (inited & INIT_INPUT_WMI_2)
+               wmi_remove_notify_handler(WMI_EVENT_GUID2);
+
+       if (inited & INIT_INPUT_WMI_0)
+               wmi_remove_notify_handler(WMI_EVENT_GUID0);
+
+       if (inited & INIT_SPARSE_KEYMAP)
+               input_unregister_device(wmi_input_dev);
+
+       inited &= ~(INIT_INPUT_WMI_0 | INIT_INPUT_WMI_2 | INIT_SPARSE_KEYMAP);
+}
+
+static struct platform_driver pf_driver = {
+       .driver = {
+                  .name = PLATFORM_NAME,
+       }
+};
+
+static int acpi_add(struct acpi_device *device)
+{
+       int ret;
+
+       if (pf_device)
+               return 0;
+
+       ret = platform_driver_register(&pf_driver);
+       if (ret)
+               return ret;
+
+       pf_device = platform_device_register_simple(PLATFORM_NAME,
+                                                   PLATFORM_DEVID_NONE,
+                                                   NULL, 0);
+       if (IS_ERR(pf_device)) {
+               ret = PTR_ERR(pf_device);
+               pf_device = NULL;
+               pr_err("unable to register platform device\n");
+               goto out_platform_registered;
+       }
+
+       ret = sysfs_create_group(&pf_device->dev.kobj, &dev_attribute_group);
+       if (ret)
+               goto out_platform_device;
+
+       if (!led_classdev_register(&pf_device->dev, &kbd_backlight))
+               inited |= INIT_KBD_LED;
+
+       if (!led_classdev_register(&pf_device->dev, &tpad_led))
+               inited |= INIT_TPAD_LED;
+
+       wmi_input_setup();
+
+       return 0;
+
+out_platform_device:
+       platform_device_unregister(pf_device);
+out_platform_registered:
+       platform_driver_unregister(&pf_driver);
+       return ret;
+}
+
+static int acpi_remove(struct acpi_device *device)
+{
+       sysfs_remove_group(&pf_device->dev.kobj, &dev_attribute_group);
+       if (inited & INIT_KBD_LED)
+               led_classdev_unregister(&kbd_backlight);
+
+       if (inited & INIT_TPAD_LED)
+               led_classdev_unregister(&tpad_led);
+
+       wmi_input_destroy();
+       platform_device_unregister(pf_device);
+       pf_device = NULL;
+       platform_driver_unregister(&pf_driver);
+
+       return 0;
+}
+
+static const struct acpi_device_id device_ids[] = {
+       {"LGEX0815", 0},
+       {"", 0}
+};
+MODULE_DEVICE_TABLE(acpi, device_ids);
+
+static struct acpi_driver acpi_driver = {
+       .name = "LG Gram Laptop Support",
+       .class = "lg-laptop",
+       .ids = device_ids,
+       .ops = {
+               .add = acpi_add,
+               .remove = acpi_remove,
+               .notify = acpi_notify,
+               },
+       .owner = THIS_MODULE,
+};
+
+static int __init acpi_init(void)
+{
+       int result;
+
+       result = acpi_bus_register_driver(&acpi_driver);
+       if (result < 0) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering driver\n"));
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void __exit acpi_exit(void)
+{
+       acpi_bus_unregister_driver(&acpi_driver);
+}
+
+module_init(acpi_init);
+module_exit(acpi_exit);
index d89936c93ba0fe069900d739e6f8d8ac1e02f902..c2c3a1a19879596bd905952a9e028e96ea7cba01 100644 (file)
@@ -575,7 +575,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = {
 
 static
 struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = {
-       .items = mlxplat_mlxcpld_msn21xx_items,
+       .items = mlxplat_mlxcpld_msn201x_items,
        .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items),
        .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
        .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
index cb204f9734913a4cc40b656bb125f8ac1e3c22b4..5f2d7ea912b56e89beb0fa75f8d502e1ef3e9f99 100644 (file)
@@ -42,10 +42,13 @@ static const struct ts_dmi_data chuwi_hi8_data = {
 };
 
 static const struct property_entry chuwi_hi8_pro_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 6),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 3),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
@@ -56,6 +59,8 @@ static const struct ts_dmi_data chuwi_hi8_pro_data = {
 };
 
 static const struct property_entry chuwi_vi8_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 4),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 6),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1724),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
@@ -88,9 +93,9 @@ static const struct ts_dmi_data chuwi_vi10_data = {
 
 static const struct property_entry connect_tablet9_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-min-x", 9),
-       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 10),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1664),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 878),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
        PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-connect-tablet9.fw"),
@@ -104,8 +109,10 @@ static const struct ts_dmi_data connect_tablet9_data = {
 };
 
 static const struct property_entry cube_iwork8_air_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 3),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1664),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 896),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
@@ -179,11 +186,14 @@ static const struct ts_dmi_data gp_electronic_t701_data = {
 };
 
 static const struct property_entry itworks_tw891_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 5),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 890),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 896),
        PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        { }
 };
 
@@ -207,8 +217,10 @@ static const struct ts_dmi_data jumper_ezpad_6_pro_data = {
 };
 
 static const struct property_entry jumper_ezpad_mini3_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 23),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1138),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
@@ -237,6 +249,24 @@ static const struct ts_dmi_data onda_obook_20_plus_data = {
        .properties     = onda_obook_20_plus_props,
 };
 
+static const struct property_entry onda_v80_plus_v3_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 22),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 15),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1698),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl3676-onda-v80-plus-v3.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data onda_v80_plus_v3_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = onda_v80_plus_v3_props,
+};
+
 static const struct property_entry onda_v820w_32g_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
@@ -322,11 +352,14 @@ static const struct ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
 };
 
 static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1794),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name",
                              "gsl3692-pov-mobii-wintab-p800w.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
@@ -366,6 +399,22 @@ static const struct ts_dmi_data teclast_x98plus2_data = {
        .properties     = teclast_x98plus2_props,
 };
 
+static const struct property_entry trekstor_primebook_c11_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1970),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1530),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl1680-trekstor-primebook-c11.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data trekstor_primebook_c11_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = trekstor_primebook_c11_props,
+};
+
 static const struct property_entry trekstor_primebook_c13_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 2624),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
@@ -381,6 +430,22 @@ static const struct ts_dmi_data trekstor_primebook_c13_data = {
        .properties     = trekstor_primebook_c13_props,
 };
 
+static const struct property_entry trekstor_primetab_t13b_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 2500),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1900),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl1680-trekstor-primetab-t13b.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+       { }
+};
+
+static const struct ts_dmi_data trekstor_primetab_t13b_data = {
+       .acpi_name  = "MSSL1680:00",
+       .properties = trekstor_primetab_t13b_props,
+};
+
 static const struct property_entry trekstor_surftab_twin_10_1_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
@@ -397,6 +462,8 @@ static const struct ts_dmi_data trekstor_surftab_twin_10_1_data = {
 };
 
 static const struct property_entry trekstor_surftab_wintron70_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 12),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
        PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
        PROPERTY_ENTRY_STRING("firmware-name",
@@ -555,6 +622,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "OBOOK 20 PLUS"),
                },
        },
+       {
+               /* ONDA V80 plus v3 (P80PSBG9V3A01501) */
+               .driver_data = (void *)&onda_v80_plus_v3_data,
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONDA"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "V80 PLUS")
+               },
+       },
        {
                /* ONDA V820w DualOS */
                .driver_data = (void *)&onda_v820w_32g_data,
@@ -640,6 +715,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
                },
        },
+       {
+               /* Trekstor Primebook C11 */
+               .driver_data = (void *)&trekstor_primebook_c11_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C11"),
+               },
+       },
        {
                /* Trekstor Primebook C13 */
                .driver_data = (void *)&trekstor_primebook_c13_data,
@@ -648,6 +731,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
                },
        },
+       {
+               /* Trekstor Primetab T13B */
+               .driver_data = (void *)&trekstor_primetab_t13b_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Primetab T13B"),
+               },
+       },
        {
                /* TrekStor SurfTab twin 10.1 ST10432-8 */
                .driver_data = (void *)&trekstor_surftab_twin_10_1_data,
index 04791ea5d97b69f9ed9fc30fb7de46cf2370acbe..bea35be68706d733cf156b993fe0a8b3d3a675e5 100644 (file)
@@ -987,19 +987,19 @@ static struct bus_type wmi_bus_type = {
        .remove = wmi_dev_remove,
 };
 
-static struct device_type wmi_type_event = {
+static const struct device_type wmi_type_event = {
        .name = "event",
        .groups = wmi_event_groups,
        .release = wmi_dev_release,
 };
 
-static struct device_type wmi_type_method = {
+static const struct device_type wmi_type_method = {
        .name = "method",
        .groups = wmi_method_groups,
        .release = wmi_dev_release,
 };
 
-static struct device_type wmi_type_data = {
+static const struct device_type wmi_type_data = {
        .name = "data",
        .groups = wmi_data_groups,
        .release = wmi_dev_release,
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
new file mode 100644 (file)
index 0000000..53dfc25
--- /dev/null
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PLATFORM_DATA_X86_ASUS_WMI_H
+#define __PLATFORM_DATA_X86_ASUS_WMI_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+/* WMI Methods */
+#define ASUS_WMI_METHODID_SPEC         0x43455053 /* BIOS SPECification */
+#define ASUS_WMI_METHODID_SFBD         0x44424653 /* Set First Boot Device */
+#define ASUS_WMI_METHODID_GLCD         0x44434C47 /* Get LCD status */
+#define ASUS_WMI_METHODID_GPID         0x44495047 /* Get Panel ID?? (Resol) */
+#define ASUS_WMI_METHODID_QMOD         0x444F4D51 /* Quiet MODe */
+#define ASUS_WMI_METHODID_SPLV         0x4C425053 /* Set Panel Light Value */
+#define ASUS_WMI_METHODID_AGFN         0x4E464741 /* FaN? */
+#define ASUS_WMI_METHODID_SFUN         0x4E554653 /* FUNCtionalities */
+#define ASUS_WMI_METHODID_SDSP         0x50534453 /* Set DiSPlay output */
+#define ASUS_WMI_METHODID_GDSP         0x50534447 /* Get DiSPlay output */
+#define ASUS_WMI_METHODID_DEVP         0x50564544 /* DEVice Policy */
+#define ASUS_WMI_METHODID_OSVR         0x5256534F /* OS VeRsion */
+#define ASUS_WMI_METHODID_DSTS         0x53544344 /* Device STatuS */
+#define ASUS_WMI_METHODID_DSTS2                0x53545344 /* Device STatuS #2*/
+#define ASUS_WMI_METHODID_BSTS         0x53545342 /* Bios STatuS ? */
+#define ASUS_WMI_METHODID_DEVS         0x53564544 /* DEVice Set */
+#define ASUS_WMI_METHODID_CFVS         0x53564643 /* CPU Frequency Volt Set */
+#define ASUS_WMI_METHODID_KBFT         0x5446424B /* KeyBoard FilTer */
+#define ASUS_WMI_METHODID_INIT         0x54494E49 /* INITialize */
+#define ASUS_WMI_METHODID_HKEY         0x59454B48 /* Hot KEY ?? */
+
+#define ASUS_WMI_UNSUPPORTED_METHOD    0xFFFFFFFE
+
+/* Wireless */
+#define ASUS_WMI_DEVID_HW_SWITCH       0x00010001
+#define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
+#define ASUS_WMI_DEVID_CWAP            0x00010003
+#define ASUS_WMI_DEVID_WLAN            0x00010011
+#define ASUS_WMI_DEVID_WLAN_LED                0x00010012
+#define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
+#define ASUS_WMI_DEVID_GPS             0x00010015
+#define ASUS_WMI_DEVID_WIMAX           0x00010017
+#define ASUS_WMI_DEVID_WWAN3G          0x00010019
+#define ASUS_WMI_DEVID_UWB             0x00010021
+
+/* Leds */
+/* 0x000200XX and 0x000400XX */
+#define ASUS_WMI_DEVID_LED1            0x00020011
+#define ASUS_WMI_DEVID_LED2            0x00020012
+#define ASUS_WMI_DEVID_LED3            0x00020013
+#define ASUS_WMI_DEVID_LED4            0x00020014
+#define ASUS_WMI_DEVID_LED5            0x00020015
+#define ASUS_WMI_DEVID_LED6            0x00020016
+
+/* Backlight and Brightness */
+#define ASUS_WMI_DEVID_ALS_ENABLE      0x00050001 /* Ambient Light Sensor */
+#define ASUS_WMI_DEVID_BACKLIGHT       0x00050011
+#define ASUS_WMI_DEVID_BRIGHTNESS      0x00050012
+#define ASUS_WMI_DEVID_KBD_BACKLIGHT   0x00050021
+#define ASUS_WMI_DEVID_LIGHT_SENSOR    0x00050022 /* ?? */
+#define ASUS_WMI_DEVID_LIGHTBAR                0x00050025
+
+/* Misc */
+#define ASUS_WMI_DEVID_CAMERA          0x00060013
+
+/* Storage */
+#define ASUS_WMI_DEVID_CARDREADER      0x00080013
+
+/* Input */
+#define ASUS_WMI_DEVID_TOUCHPAD                0x00100011
+#define ASUS_WMI_DEVID_TOUCHPAD_LED    0x00100012
+
+/* Fan, Thermal */
+#define ASUS_WMI_DEVID_THERMAL_CTRL    0x00110011
+#define ASUS_WMI_DEVID_FAN_CTRL                0x00110012
+
+/* Power */
+#define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
+
+/* Deep S3 / Resume on LID open */
+#define ASUS_WMI_DEVID_LID_RESUME      0x00120031
+
+/* DSTS masks */
+#define ASUS_WMI_DSTS_STATUS_BIT       0x00000001
+#define ASUS_WMI_DSTS_UNKNOWN_BIT      0x00000002
+#define ASUS_WMI_DSTS_PRESENCE_BIT     0x00010000
+#define ASUS_WMI_DSTS_USER_BIT         0x00020000
+#define ASUS_WMI_DSTS_BIOS_BIT         0x00040000
+#define ASUS_WMI_DSTS_BRIGHTNESS_MASK  0x000000FF
+#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK  0x0000FF00
+#define ASUS_WMI_DSTS_LIGHTBAR_MASK    0x0000000F
+
+#if IS_REACHABLE(CONFIG_ASUS_WMI)
+int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval);
+#else
+static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
+                                          u32 *retval)
+{
+       return -ENODEV;
+}
+#endif
+
+#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */
index b0875b327f5c3d5c733f79337bef40d5d600fbd1..c3fd849d4a8f93c27d18713ae1e492faa5d24ec9 100644 (file)
@@ -115,7 +115,7 @@ static int module_trace_bprintk_format_notify(struct notifier_block *self,
  * section, then we need to read the link list pointers. The trick is
  * we pass the address of the string to the seq function just like
  * we do for the kernel core formats. To get back the structure that
- * holds the format, we simply use containerof() and then go to the
+ * holds the format, we simply use container_of() and then go to the
  * next format in the list.
  */
 static const char **