alistair23-linux/drivers/platform/x86/intel_mid_powerbtn.c
Linus Torvalds eb7046e9bf platform-drivers-x86 for v4.20-1
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.
 
 The following is an automated git shortlog grouped by driver:
 
 Add Intel AtomISP2 dummy / power-management driver:
  - Add Intel AtomISP2 dummy / power-management driver
 
 lg-laptop:
  - Add LG Gram laptop special features driver
 
 HID:
  -  asus: only support backlight when it's not driven by WMI
 
 MAINTAINERS:
  -  intel_telemetry: Update maintainers info
  -  intel_pmc_core: Update MAINTAINERS
  -  Update maintainer for dcdbas and dell_rbu
  -  Use my infradead account exclusively for PDx86 work
 
 acerhdf:
  -  restructure to allow large BIOS table be __initconst
  -  mark appropriate content with __init prefix
  -  Add BIOS entry for Gateway LT31 v1.3307
  -  Remove cut-and-paste trap from instructions
  -  Enable ability to list supported systems
  -  clarify modinfo messages for BIOS override
 
 asus-wmi:
  -  export function for evaluating WMI methods
  -  Only notify kbd LED hw_change by fn-key pressed
  -  Simplify the keyboard brightness updating process
 
 firmware:
  -  dcdbas: include linux/io.h
  -  dcdbas: Move dcdbas to drivers/platform/x86
  -  dell_rbu: Move dell_rbu to drivers/platform/x86
  -  dcdbas: Add support for WSMT ACPI table
  -  dell_rbu: Make payload memory uncachable
 
 ideapad-laptop:
  -  Add Y530-15ICH to no_hw_rfkill
  -  Use __func__ instead of read_ec_cmd in pr_err
 
 intel-hid:
  -  Convert to use SPDX identifier
 
 intel-ips:
  -  Convert to use SPDX identifier
 
 intel-rst:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 intel-smartconnect:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 intel-wmi-thunderbolt:
  -  Add dynamic debugging
  -  Convert to use SPDX identifier
 
 intel_bxtwc_tmu:
  -  Convert to use SPDX identifier
 
 intel_cht_int33fe:
  -  Convert to use SPDX identifier
 
 intel_chtdc_ti_pwrbtn:
  -  Add SPDX identifier
 
 intel_int0002_vgpio:
  -  Convert to use SPDX identifier
  -  Implement irq_set_wake
  -  Enable the driver on Bay Trail platforms
 
 intel_menlow:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 intel_mid_powerbtn:
  -  Convert to use SPDX identifier
  -  Remove unnecessary init.h inclusion
  -  Get rid of custom ICPU() macro
 
 intel_mid_thermal:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 intel_oaktrail:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 intel_pmc:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 intel_punit_ipc:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 intel_scu_ipc:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 intel_telemetry:
  -  Get rid of custom macro
  -  report debugfs failure
  -  Convert to use SPDX identifier
 
 intel_turbo_max_3:
  -  Convert to use SPDX identifier
  -  Sort headers alphabetically
 
 mlx-platform:
  -  Properly use mlxplat_mlxcpld_msn201x_items
 
 touchscreen_dmi:
  -  Add min-x and min-y settings for various models
  -  Add info for the Onda V80 Plus v3 tablet
  -  Add info for the Trekstor Primetab T13B tablet
  -  Add info for the Trekstor Primebook C11 convertible
 
 tracing:
  -  Trivia spelling fix containerof() -> container_of()
 
 wmi:
  -  declare device_type structure as constant
 -----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJb2mDCAAoJEKbMaAwKp364KdkH/Rar8cenw7uFeVzT5o4fGzTn
 0Oo1Pnwh+hPgmQwmf8O/mHsa/1Zb9nX4nNLU/ysDUjAAZ9wZLoB57HlImQquPA74
 c8lXTz5MVF140WB1f1Ck5PmeonJR2Xve7HTYCoBmGo71jOxHxCgJbp1Giiho0Imd
 3NXzzahEnAiy/L5PhqqYTmIfTeAHQ2Fo7GkHCjMnS20FP2fBtvPrc7db03F+FZ4y
 QTfbT0oR42NdeW21AbCRGY3P47axB3xDJX4LOYrb4uo4CIzd1yatlHk407NRRyv8
 pab6aeJR23FouA/tcvv+T36D3vqRw78e6BWdoyowWOd7CUOgjtSC3lKGzfT6hSY=
 =0BDZ
 -----END PGP SIGNATURE-----

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

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
  ...
2018-11-01 08:42:21 -07:00

226 lines
5.2 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Power button driver for Intel MID platforms.
*
* Copyright (C) 2010,2017 Intel Corp
*
* Author: Hong Liu <hong.liu@intel.com>
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*/
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/mfd/intel_msic.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
#include <linux/slab.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/intel_scu_ipc.h>
#define DRIVER_NAME "msic_power_btn"
#define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */
/*
* MSIC document ti_datasheet defines the 1st bit reg 0x21 is used to mask
* power button interrupt
*/
#define MSIC_PWRBTNM (1 << 0)
/* Intel Tangier */
#define BCOVE_PB_LEVEL (1 << 4) /* 1 - release, 0 - press */
/* Basin Cove PMIC */
#define BCOVE_PBIRQ 0x02
#define BCOVE_IRQLVL1MSK 0x0c
#define BCOVE_PBIRQMASK 0x0d
#define BCOVE_PBSTATUS 0x27
struct mid_pb_ddata {
struct device *dev;
int irq;
struct input_dev *input;
unsigned short mirqlvl1_addr;
unsigned short pbstat_addr;
u8 pbstat_mask;
int (*setup)(struct mid_pb_ddata *ddata);
};
static int mid_pbstat(struct mid_pb_ddata *ddata, int *value)
{
struct input_dev *input = ddata->input;
int ret;
u8 pbstat;
ret = intel_scu_ipc_ioread8(ddata->pbstat_addr, &pbstat);
if (ret)
return ret;
dev_dbg(input->dev.parent, "PB_INT status= %d\n", pbstat);
*value = !(pbstat & ddata->pbstat_mask);
return 0;
}
static int mid_irq_ack(struct mid_pb_ddata *ddata)
{
return intel_scu_ipc_update_register(ddata->mirqlvl1_addr, 0, MSIC_PWRBTNM);
}
static int mrfld_setup(struct mid_pb_ddata *ddata)
{
/* Unmask the PBIRQ and MPBIRQ on Tangier */
intel_scu_ipc_update_register(BCOVE_PBIRQ, 0, MSIC_PWRBTNM);
intel_scu_ipc_update_register(BCOVE_PBIRQMASK, 0, MSIC_PWRBTNM);
return 0;
}
static irqreturn_t mid_pb_isr(int irq, void *dev_id)
{
struct mid_pb_ddata *ddata = dev_id;
struct input_dev *input = ddata->input;
int value = 0;
int ret;
ret = mid_pbstat(ddata, &value);
if (ret < 0) {
dev_err(input->dev.parent,
"Read error %d while reading MSIC_PB_STATUS\n", ret);
} else {
input_event(input, EV_KEY, KEY_POWER, value);
input_sync(input);
}
mid_irq_ack(ddata);
return IRQ_HANDLED;
}
static const struct mid_pb_ddata mfld_ddata = {
.mirqlvl1_addr = INTEL_MSIC_IRQLVL1MSK,
.pbstat_addr = INTEL_MSIC_PBSTATUS,
.pbstat_mask = MSIC_PB_LEVEL,
};
static const struct mid_pb_ddata mrfld_ddata = {
.mirqlvl1_addr = BCOVE_IRQLVL1MSK,
.pbstat_addr = BCOVE_PBSTATUS,
.pbstat_mask = BCOVE_PB_LEVEL,
.setup = mrfld_setup,
};
static const struct x86_cpu_id mid_pb_cpu_ids[] = {
INTEL_CPU_FAM6(ATOM_SALTWELL_MID, mfld_ddata),
INTEL_CPU_FAM6(ATOM_SILVERMONT_MID, mrfld_ddata),
{}
};
static int mid_pb_probe(struct platform_device *pdev)
{
const struct x86_cpu_id *id;
struct mid_pb_ddata *ddata;
struct input_dev *input;
int irq = platform_get_irq(pdev, 0);
int error;
id = x86_match_cpu(mid_pb_cpu_ids);
if (!id)
return -ENODEV;
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
return irq;
}
input = devm_input_allocate_device(&pdev->dev);
if (!input)
return -ENOMEM;
input->name = pdev->name;
input->phys = "power-button/input0";
input->id.bustype = BUS_HOST;
input->dev.parent = &pdev->dev;
input_set_capability(input, EV_KEY, KEY_POWER);
ddata = (struct mid_pb_ddata *)id->driver_data;
if (!ddata)
return -ENODATA;
ddata->dev = &pdev->dev;
ddata->irq = irq;
ddata->input = input;
if (ddata->setup) {
error = ddata->setup(ddata);
if (error)
return error;
}
error = devm_request_threaded_irq(&pdev->dev, irq, NULL, mid_pb_isr,
IRQF_ONESHOT, DRIVER_NAME, ddata);
if (error) {
dev_err(&pdev->dev,
"Unable to request irq %d for MID power button\n", irq);
return error;
}
error = input_register_device(input);
if (error) {
dev_err(&pdev->dev,
"Unable to register input dev, error %d\n", error);
return error;
}
platform_set_drvdata(pdev, ddata);
/*
* SCU firmware might send power button interrupts to IA core before
* kernel boots and doesn't get EOI from IA core. The first bit of
* MSIC reg 0x21 is kept masked, and SCU firmware doesn't send new
* power interrupt to Android kernel. Unmask the bit when probing
* power button in kernel.
* There is a very narrow race between irq handler and power button
* initialization. The race happens rarely. So we needn't worry
* about it.
*/
error = mid_irq_ack(ddata);
if (error) {
dev_err(&pdev->dev,
"Unable to clear power button interrupt, error: %d\n",
error);
return error;
}
device_init_wakeup(&pdev->dev, true);
dev_pm_set_wake_irq(&pdev->dev, irq);
return 0;
}
static int mid_pb_remove(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
return 0;
}
static struct platform_driver mid_pb_driver = {
.driver = {
.name = DRIVER_NAME,
},
.probe = mid_pb_probe,
.remove = mid_pb_remove,
};
module_platform_driver(mid_pb_driver);
MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
MODULE_DESCRIPTION("Intel MID Power Button Driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRIVER_NAME);