cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

soc_button_array.c (17088B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Supports for the button array on SoC tablets originally running
      4 * Windows 8.
      5 *
      6 * (C) Copyright 2014 Intel Corporation
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/input.h>
     11#include <linux/init.h>
     12#include <linux/irq.h>
     13#include <linux/kernel.h>
     14#include <linux/acpi.h>
     15#include <linux/dmi.h>
     16#include <linux/gpio/consumer.h>
     17#include <linux/gpio_keys.h>
     18#include <linux/gpio.h>
     19#include <linux/platform_device.h>
     20
     21struct soc_button_info {
     22	const char *name;
     23	int acpi_index;
     24	unsigned int event_type;
     25	unsigned int event_code;
     26	bool autorepeat;
     27	bool wakeup;
     28	bool active_low;
     29};
     30
     31struct soc_device_data {
     32	const struct soc_button_info *button_info;
     33	int (*check)(struct device *dev);
     34};
     35
     36/*
     37 * Some of the buttons like volume up/down are auto repeat, while others
     38 * are not. To support both, we register two platform devices, and put
     39 * buttons into them based on whether the key should be auto repeat.
     40 */
     41#define BUTTON_TYPES	2
     42
     43struct soc_button_data {
     44	struct platform_device *children[BUTTON_TYPES];
     45};
     46
     47/*
     48 * Some 2-in-1s which use the soc_button_array driver have this ugly issue in
     49 * their DSDT where the _LID method modifies the irq-type settings of the GPIOs
     50 * used for the power and home buttons. The intend of this AML code is to
     51 * disable these buttons when the lid is closed.
     52 * The AML does this by directly poking the GPIO controllers registers. This is
     53 * problematic because when re-enabling the irq, which happens whenever _LID
     54 * gets called with the lid open (e.g. on boot and on resume), it sets the
     55 * irq-type to IRQ_TYPE_LEVEL_LOW. Where as the gpio-keys driver programs the
     56 * type to, and expects it to be, IRQ_TYPE_EDGE_BOTH.
     57 * To work around this we don't set gpio_keys_button.gpio on these 2-in-1s,
     58 * instead we get the irq for the GPIO ourselves, configure it as
     59 * IRQ_TYPE_LEVEL_LOW (to match how the _LID AML code configures it) and pass
     60 * the irq in gpio_keys_button.irq. Below is a list of affected devices.
     61 */
     62static const struct dmi_system_id dmi_use_low_level_irq[] = {
     63	{
     64		/*
     65		 * Acer Switch 10 SW5-012. _LID method messes with home- and
     66		 * power-button GPIO IRQ settings. When (re-)enabling the irq
     67		 * it ors in its own flags without clearing the previous set
     68		 * ones, leading to an irq-type of IRQ_TYPE_LEVEL_LOW |
     69		 * IRQ_TYPE_LEVEL_HIGH causing a continuous interrupt storm.
     70		 */
     71		.matches = {
     72			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
     73			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
     74		},
     75	},
     76	{
     77		/*
     78		 * Acer One S1003. _LID method messes with power-button GPIO
     79		 * IRQ settings, leading to a non working power-button.
     80		 */
     81		.matches = {
     82			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
     83			DMI_MATCH(DMI_PRODUCT_NAME, "One S1003"),
     84		},
     85	},
     86	{
     87		/*
     88		 * Lenovo Yoga Tab2 1051F/1051L, something messes with the home-button
     89		 * IRQ settings, leading to a non working home-button.
     90		 */
     91		.matches = {
     92			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
     93			DMI_MATCH(DMI_PRODUCT_NAME, "60073"),
     94			DMI_MATCH(DMI_PRODUCT_VERSION, "1051"),
     95		},
     96	},
     97	{} /* Terminating entry */
     98};
     99
    100/*
    101 * Get the Nth GPIO number from the ACPI object.
    102 */
    103static int soc_button_lookup_gpio(struct device *dev, int acpi_index,
    104				  int *gpio_ret, int *irq_ret)
    105{
    106	struct gpio_desc *desc;
    107
    108	desc = gpiod_get_index(dev, NULL, acpi_index, GPIOD_ASIS);
    109	if (IS_ERR(desc))
    110		return PTR_ERR(desc);
    111
    112	*gpio_ret = desc_to_gpio(desc);
    113	*irq_ret = gpiod_to_irq(desc);
    114
    115	gpiod_put(desc);
    116
    117	return 0;
    118}
    119
    120static struct platform_device *
    121soc_button_device_create(struct platform_device *pdev,
    122			 const struct soc_button_info *button_info,
    123			 bool autorepeat)
    124{
    125	const struct soc_button_info *info;
    126	struct platform_device *pd;
    127	struct gpio_keys_button *gpio_keys;
    128	struct gpio_keys_platform_data *gpio_keys_pdata;
    129	int error, gpio, irq;
    130	int n_buttons = 0;
    131
    132	for (info = button_info; info->name; info++)
    133		if (info->autorepeat == autorepeat)
    134			n_buttons++;
    135
    136	gpio_keys_pdata = devm_kzalloc(&pdev->dev,
    137				       sizeof(*gpio_keys_pdata) +
    138					sizeof(*gpio_keys) * n_buttons,
    139				       GFP_KERNEL);
    140	if (!gpio_keys_pdata)
    141		return ERR_PTR(-ENOMEM);
    142
    143	gpio_keys = (void *)(gpio_keys_pdata + 1);
    144	n_buttons = 0;
    145
    146	for (info = button_info; info->name; info++) {
    147		if (info->autorepeat != autorepeat)
    148			continue;
    149
    150		error = soc_button_lookup_gpio(&pdev->dev, info->acpi_index, &gpio, &irq);
    151		if (error || irq < 0) {
    152			/*
    153			 * Skip GPIO if not present. Note we deliberately
    154			 * ignore -EPROBE_DEFER errors here. On some devices
    155			 * Intel is using so called virtual GPIOs which are not
    156			 * GPIOs at all but some way for AML code to check some
    157			 * random status bits without need a custom opregion.
    158			 * In some cases the resources table we parse points to
    159			 * such a virtual GPIO, since these are not real GPIOs
    160			 * we do not have a driver for these so they will never
    161			 * show up, therefore we ignore -EPROBE_DEFER.
    162			 */
    163			continue;
    164		}
    165
    166		/* See dmi_use_low_level_irq[] comment */
    167		if (!autorepeat && dmi_check_system(dmi_use_low_level_irq)) {
    168			irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
    169			gpio_keys[n_buttons].irq = irq;
    170			gpio_keys[n_buttons].gpio = -ENOENT;
    171		} else {
    172			gpio_keys[n_buttons].gpio = gpio;
    173		}
    174
    175		gpio_keys[n_buttons].type = info->event_type;
    176		gpio_keys[n_buttons].code = info->event_code;
    177		gpio_keys[n_buttons].active_low = info->active_low;
    178		gpio_keys[n_buttons].desc = info->name;
    179		gpio_keys[n_buttons].wakeup = info->wakeup;
    180		/* These devices often use cheap buttons, use 50 ms debounce */
    181		gpio_keys[n_buttons].debounce_interval = 50;
    182		n_buttons++;
    183	}
    184
    185	if (n_buttons == 0) {
    186		error = -ENODEV;
    187		goto err_free_mem;
    188	}
    189
    190	gpio_keys_pdata->buttons = gpio_keys;
    191	gpio_keys_pdata->nbuttons = n_buttons;
    192	gpio_keys_pdata->rep = autorepeat;
    193
    194	pd = platform_device_register_resndata(&pdev->dev, "gpio-keys",
    195					       PLATFORM_DEVID_AUTO, NULL, 0,
    196					       gpio_keys_pdata,
    197					       sizeof(*gpio_keys_pdata));
    198	error = PTR_ERR_OR_ZERO(pd);
    199	if (error) {
    200		dev_err(&pdev->dev,
    201			"failed registering gpio-keys: %d\n", error);
    202		goto err_free_mem;
    203	}
    204
    205	return pd;
    206
    207err_free_mem:
    208	devm_kfree(&pdev->dev, gpio_keys_pdata);
    209	return ERR_PTR(error);
    210}
    211
    212static int soc_button_get_acpi_object_int(const union acpi_object *obj)
    213{
    214	if (obj->type != ACPI_TYPE_INTEGER)
    215		return -1;
    216
    217	return obj->integer.value;
    218}
    219
    220/* Parse a single ACPI0011 _DSD button descriptor */
    221static int soc_button_parse_btn_desc(struct device *dev,
    222				     const union acpi_object *desc,
    223				     int collection_uid,
    224				     struct soc_button_info *info)
    225{
    226	int upage, usage;
    227
    228	if (desc->type != ACPI_TYPE_PACKAGE ||
    229	    desc->package.count != 5 ||
    230	    /* First byte should be 1 (control) */
    231	    soc_button_get_acpi_object_int(&desc->package.elements[0]) != 1 ||
    232	    /* Third byte should be collection uid */
    233	    soc_button_get_acpi_object_int(&desc->package.elements[2]) !=
    234							    collection_uid) {
    235		dev_err(dev, "Invalid ACPI Button Descriptor\n");
    236		return -ENODEV;
    237	}
    238
    239	info->event_type = EV_KEY;
    240	info->active_low = true;
    241	info->acpi_index =
    242		soc_button_get_acpi_object_int(&desc->package.elements[1]);
    243	upage = soc_button_get_acpi_object_int(&desc->package.elements[3]);
    244	usage = soc_button_get_acpi_object_int(&desc->package.elements[4]);
    245
    246	/*
    247	 * The UUID: fa6bd625-9ce8-470d-a2c7-b3ca36c4282e descriptors use HID
    248	 * usage page and usage codes, but otherwise the device is not HID
    249	 * compliant: it uses one irq per button instead of generating HID
    250	 * input reports and some buttons should generate wakeups where as
    251	 * others should not, so we cannot use the HID subsystem.
    252	 *
    253	 * Luckily all devices only use a few usage page + usage combinations,
    254	 * so we can simply check for the known combinations here.
    255	 */
    256	if (upage == 0x01 && usage == 0x81) {
    257		info->name = "power";
    258		info->event_code = KEY_POWER;
    259		info->wakeup = true;
    260	} else if (upage == 0x01 && usage == 0xca) {
    261		info->name = "rotation lock switch";
    262		info->event_type = EV_SW;
    263		info->event_code = SW_ROTATE_LOCK;
    264	} else if (upage == 0x07 && usage == 0xe3) {
    265		info->name = "home";
    266		info->event_code = KEY_LEFTMETA;
    267		info->wakeup = true;
    268	} else if (upage == 0x0c && usage == 0xe9) {
    269		info->name = "volume_up";
    270		info->event_code = KEY_VOLUMEUP;
    271		info->autorepeat = true;
    272	} else if (upage == 0x0c && usage == 0xea) {
    273		info->name = "volume_down";
    274		info->event_code = KEY_VOLUMEDOWN;
    275		info->autorepeat = true;
    276	} else {
    277		dev_warn(dev, "Unknown button index %d upage %02x usage %02x, ignoring\n",
    278			 info->acpi_index, upage, usage);
    279		info->name = "unknown";
    280		info->event_code = KEY_RESERVED;
    281	}
    282
    283	return 0;
    284}
    285
    286/* ACPI0011 _DSD btns descriptors UUID: fa6bd625-9ce8-470d-a2c7-b3ca36c4282e */
    287static const u8 btns_desc_uuid[16] = {
    288	0x25, 0xd6, 0x6b, 0xfa, 0xe8, 0x9c, 0x0d, 0x47,
    289	0xa2, 0xc7, 0xb3, 0xca, 0x36, 0xc4, 0x28, 0x2e
    290};
    291
    292/* Parse ACPI0011 _DSD button descriptors */
    293static struct soc_button_info *soc_button_get_button_info(struct device *dev)
    294{
    295	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
    296	const union acpi_object *desc, *el0, *uuid, *btns_desc = NULL;
    297	struct soc_button_info *button_info;
    298	acpi_status status;
    299	int i, btn, collection_uid = -1;
    300
    301	status = acpi_evaluate_object_typed(ACPI_HANDLE(dev), "_DSD", NULL,
    302					    &buf, ACPI_TYPE_PACKAGE);
    303	if (ACPI_FAILURE(status)) {
    304		dev_err(dev, "ACPI _DSD object not found\n");
    305		return ERR_PTR(-ENODEV);
    306	}
    307
    308	/* Look for the Button Descriptors UUID */
    309	desc = buf.pointer;
    310	for (i = 0; (i + 1) < desc->package.count; i += 2) {
    311		uuid = &desc->package.elements[i];
    312
    313		if (uuid->type != ACPI_TYPE_BUFFER ||
    314		    uuid->buffer.length != 16 ||
    315		    desc->package.elements[i + 1].type != ACPI_TYPE_PACKAGE) {
    316			break;
    317		}
    318
    319		if (memcmp(uuid->buffer.pointer, btns_desc_uuid, 16) == 0) {
    320			btns_desc = &desc->package.elements[i + 1];
    321			break;
    322		}
    323	}
    324
    325	if (!btns_desc) {
    326		dev_err(dev, "ACPI Button Descriptors not found\n");
    327		button_info = ERR_PTR(-ENODEV);
    328		goto out;
    329	}
    330
    331	/* The first package describes the collection */
    332	el0 = &btns_desc->package.elements[0];
    333	if (el0->type == ACPI_TYPE_PACKAGE &&
    334	    el0->package.count == 5 &&
    335	    /* First byte should be 0 (collection) */
    336	    soc_button_get_acpi_object_int(&el0->package.elements[0]) == 0 &&
    337	    /* Third byte should be 0 (top level collection) */
    338	    soc_button_get_acpi_object_int(&el0->package.elements[2]) == 0) {
    339		collection_uid = soc_button_get_acpi_object_int(
    340						&el0->package.elements[1]);
    341	}
    342	if (collection_uid == -1) {
    343		dev_err(dev, "Invalid Button Collection Descriptor\n");
    344		button_info = ERR_PTR(-ENODEV);
    345		goto out;
    346	}
    347
    348	/* There are package.count - 1 buttons + 1 terminating empty entry */
    349	button_info = devm_kcalloc(dev, btns_desc->package.count,
    350				   sizeof(*button_info), GFP_KERNEL);
    351	if (!button_info) {
    352		button_info = ERR_PTR(-ENOMEM);
    353		goto out;
    354	}
    355
    356	/* Parse the button descriptors */
    357	for (i = 1, btn = 0; i < btns_desc->package.count; i++, btn++) {
    358		if (soc_button_parse_btn_desc(dev,
    359					      &btns_desc->package.elements[i],
    360					      collection_uid,
    361					      &button_info[btn])) {
    362			button_info = ERR_PTR(-ENODEV);
    363			goto out;
    364		}
    365	}
    366
    367out:
    368	kfree(buf.pointer);
    369	return button_info;
    370}
    371
    372static int soc_button_remove(struct platform_device *pdev)
    373{
    374	struct soc_button_data *priv = platform_get_drvdata(pdev);
    375
    376	int i;
    377
    378	for (i = 0; i < BUTTON_TYPES; i++)
    379		if (priv->children[i])
    380			platform_device_unregister(priv->children[i]);
    381
    382	return 0;
    383}
    384
    385static int soc_button_probe(struct platform_device *pdev)
    386{
    387	struct device *dev = &pdev->dev;
    388	const struct soc_device_data *device_data;
    389	const struct soc_button_info *button_info;
    390	struct soc_button_data *priv;
    391	struct platform_device *pd;
    392	int i;
    393	int error;
    394
    395	device_data = acpi_device_get_match_data(dev);
    396	if (device_data && device_data->check) {
    397		error = device_data->check(dev);
    398		if (error)
    399			return error;
    400	}
    401
    402	if (device_data && device_data->button_info) {
    403		button_info = device_data->button_info;
    404	} else {
    405		button_info = soc_button_get_button_info(dev);
    406		if (IS_ERR(button_info))
    407			return PTR_ERR(button_info);
    408	}
    409
    410	error = gpiod_count(dev, NULL);
    411	if (error < 0) {
    412		dev_dbg(dev, "no GPIO attached, ignoring...\n");
    413		return -ENODEV;
    414	}
    415
    416	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    417	if (!priv)
    418		return -ENOMEM;
    419
    420	platform_set_drvdata(pdev, priv);
    421
    422	for (i = 0; i < BUTTON_TYPES; i++) {
    423		pd = soc_button_device_create(pdev, button_info, i == 0);
    424		if (IS_ERR(pd)) {
    425			error = PTR_ERR(pd);
    426			if (error != -ENODEV) {
    427				soc_button_remove(pdev);
    428				return error;
    429			}
    430			continue;
    431		}
    432
    433		priv->children[i] = pd;
    434	}
    435
    436	if (!priv->children[0] && !priv->children[1])
    437		return -ENODEV;
    438
    439	if (!device_data || !device_data->button_info)
    440		devm_kfree(dev, button_info);
    441
    442	return 0;
    443}
    444
    445/*
    446 * Definition of buttons on the tablet. The ACPI index of each button
    447 * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
    448 * Platforms"
    449 */
    450static const struct soc_button_info soc_button_PNP0C40[] = {
    451	{ "power", 0, EV_KEY, KEY_POWER, false, true, true },
    452	{ "home", 1, EV_KEY, KEY_LEFTMETA, false, true, true },
    453	{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
    454	{ "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
    455	{ "rotation_lock", 4, EV_KEY, KEY_ROTATE_LOCK_TOGGLE, false, false, true },
    456	{ }
    457};
    458
    459static const struct soc_device_data soc_device_PNP0C40 = {
    460	.button_info = soc_button_PNP0C40,
    461};
    462
    463static const struct soc_button_info soc_button_INT33D3[] = {
    464	{ "tablet_mode", 0, EV_SW, SW_TABLET_MODE, false, false, false },
    465	{ }
    466};
    467
    468static const struct soc_device_data soc_device_INT33D3 = {
    469	.button_info = soc_button_INT33D3,
    470};
    471
    472/*
    473 * Button info for Microsoft Surface 3 (non pro), this is indentical to
    474 * the PNP0C40 info except that the home button is active-high.
    475 *
    476 * The Surface 3 Pro also has a MSHW0028 ACPI device, but that uses a custom
    477 * version of the drivers/platform/x86/intel/hid.c 5 button array ACPI API
    478 * instead. A check() callback is not necessary though as the Surface 3 Pro
    479 * MSHW0028 ACPI device's resource table does not contain any GPIOs.
    480 */
    481static const struct soc_button_info soc_button_MSHW0028[] = {
    482	{ "power", 0, EV_KEY, KEY_POWER, false, true, true },
    483	{ "home", 1, EV_KEY, KEY_LEFTMETA, false, true, false },
    484	{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
    485	{ "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
    486	{ }
    487};
    488
    489static const struct soc_device_data soc_device_MSHW0028 = {
    490	.button_info = soc_button_MSHW0028,
    491};
    492
    493/*
    494 * Special device check for Surface Book 2 and Surface Pro (2017).
    495 * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned
    496 * devices use MSHW0040 for power and volume buttons, however the way they
    497 * have to be addressed differs. Make sure that we only load this drivers
    498 * for the correct devices by checking the OEM Platform Revision provided by
    499 * the _DSM method.
    500 */
    501#define MSHW0040_DSM_REVISION		0x01
    502#define MSHW0040_DSM_GET_OMPR		0x02	// get OEM Platform Revision
    503static const guid_t MSHW0040_DSM_UUID =
    504	GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
    505		  0x49, 0x80, 0x35);
    506
    507static int soc_device_check_MSHW0040(struct device *dev)
    508{
    509	acpi_handle handle = ACPI_HANDLE(dev);
    510	union acpi_object *result;
    511	u64 oem_platform_rev = 0;	// valid revisions are nonzero
    512
    513	// get OEM platform revision
    514	result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
    515					 MSHW0040_DSM_REVISION,
    516					 MSHW0040_DSM_GET_OMPR, NULL,
    517					 ACPI_TYPE_INTEGER);
    518
    519	if (result) {
    520		oem_platform_rev = result->integer.value;
    521		ACPI_FREE(result);
    522	}
    523
    524	/*
    525	 * If the revision is zero here, the _DSM evaluation has failed. This
    526	 * indicates that we have a Pro 4 or Book 1 and this driver should not
    527	 * be used.
    528	 */
    529	if (oem_platform_rev == 0)
    530		return -ENODEV;
    531
    532	dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev);
    533
    534	return 0;
    535}
    536
    537/*
    538 * Button infos for Microsoft Surface Book 2 and Surface Pro (2017).
    539 * Obtained from DSDT/testing.
    540 */
    541static const struct soc_button_info soc_button_MSHW0040[] = {
    542	{ "power", 0, EV_KEY, KEY_POWER, false, true, true },
    543	{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
    544	{ "volume_down", 4, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
    545	{ }
    546};
    547
    548static const struct soc_device_data soc_device_MSHW0040 = {
    549	.button_info = soc_button_MSHW0040,
    550	.check = soc_device_check_MSHW0040,
    551};
    552
    553static const struct acpi_device_id soc_button_acpi_match[] = {
    554	{ "PNP0C40", (unsigned long)&soc_device_PNP0C40 },
    555	{ "INT33D3", (unsigned long)&soc_device_INT33D3 },
    556	{ "ID9001", (unsigned long)&soc_device_INT33D3 },
    557	{ "ACPI0011", 0 },
    558
    559	/* Microsoft Surface Devices (3th, 5th and 6th generation) */
    560	{ "MSHW0028", (unsigned long)&soc_device_MSHW0028 },
    561	{ "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
    562
    563	{ }
    564};
    565
    566MODULE_DEVICE_TABLE(acpi, soc_button_acpi_match);
    567
    568static struct platform_driver soc_button_driver = {
    569	.probe          = soc_button_probe,
    570	.remove		= soc_button_remove,
    571	.driver		= {
    572		.name = KBUILD_MODNAME,
    573		.acpi_match_table = ACPI_PTR(soc_button_acpi_match),
    574	},
    575};
    576module_platform_driver(soc_button_driver);
    577
    578MODULE_LICENSE("GPL");