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

x86-android-tablets.c (42916B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * DMI based code to deal with broken DSDTs on X86 tablets which ship with
      4 * Android as (part of) the factory image. The factory kernels shipped on these
      5 * devices typically have a bunch of things hardcoded, rather than specified
      6 * in their DSDT.
      7 *
      8 * Copyright (C) 2021 Hans de Goede <hdegoede@redhat.com>
      9 */
     10
     11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     12
     13#include <linux/acpi.h>
     14#include <linux/dmi.h>
     15#include <linux/efi.h>
     16#include <linux/gpio_keys.h>
     17#include <linux/gpio/consumer.h>
     18#include <linux/gpio/driver.h>
     19#include <linux/gpio/machine.h>
     20#include <linux/i2c.h>
     21#include <linux/input.h>
     22#include <linux/irq.h>
     23#include <linux/irqdomain.h>
     24#include <linux/module.h>
     25#include <linux/mod_devicetable.h>
     26#include <linux/pinctrl/consumer.h>
     27#include <linux/pinctrl/machine.h>
     28#include <linux/platform_data/lp855x.h>
     29#include <linux/platform_device.h>
     30#include <linux/pm.h>
     31#include <linux/power/bq24190_charger.h>
     32#include <linux/rmi.h>
     33#include <linux/serdev.h>
     34#include <linux/spi/spi.h>
     35#include <linux/string.h>
     36/* For gpio_get_desc() which is EXPORT_SYMBOL_GPL() */
     37#include "../../gpio/gpiolib.h"
     38#include "../../gpio/gpiolib-acpi.h"
     39
     40/*
     41 * Helper code to get Linux IRQ numbers given a description of the IRQ source
     42 * (either IOAPIC index, or GPIO chip name + pin-number).
     43 */
     44enum x86_acpi_irq_type {
     45	X86_ACPI_IRQ_TYPE_NONE,
     46	X86_ACPI_IRQ_TYPE_APIC,
     47	X86_ACPI_IRQ_TYPE_GPIOINT,
     48	X86_ACPI_IRQ_TYPE_PMIC,
     49};
     50
     51struct x86_acpi_irq_data {
     52	char *chip;   /* GPIO chip label (GPIOINT) or PMIC ACPI path (PMIC) */
     53	enum x86_acpi_irq_type type;
     54	enum irq_domain_bus_token domain;
     55	int index;
     56	int trigger;  /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */
     57	int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */
     58};
     59
     60static int gpiochip_find_match_label(struct gpio_chip *gc, void *data)
     61{
     62	return gc->label && !strcmp(gc->label, data);
     63}
     64
     65static int x86_android_tablet_get_gpiod(char *label, int pin, struct gpio_desc **desc)
     66{
     67	struct gpio_desc *gpiod;
     68	struct gpio_chip *chip;
     69
     70	chip = gpiochip_find(label, gpiochip_find_match_label);
     71	if (!chip) {
     72		pr_err("error cannot find GPIO chip %s\n", label);
     73		return -ENODEV;
     74	}
     75
     76	gpiod = gpiochip_get_desc(chip, pin);
     77	if (IS_ERR(gpiod)) {
     78		pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin);
     79		return PTR_ERR(gpiod);
     80	}
     81
     82	*desc = gpiod;
     83	return 0;
     84}
     85
     86static int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
     87{
     88	struct irq_fwspec fwspec = { };
     89	struct irq_domain *domain;
     90	struct acpi_device *adev;
     91	struct gpio_desc *gpiod;
     92	unsigned int irq_type;
     93	acpi_handle handle;
     94	acpi_status status;
     95	int irq, ret;
     96
     97	switch (data->type) {
     98	case X86_ACPI_IRQ_TYPE_APIC:
     99		/*
    100		 * The DSDT may already reference the GSI in a device skipped by
    101		 * acpi_quirk_skip_i2c_client_enumeration(). Unregister the GSI
    102		 * to avoid EBUSY errors in this case.
    103		 */
    104		acpi_unregister_gsi(data->index);
    105		irq = acpi_register_gsi(NULL, data->index, data->trigger, data->polarity);
    106		if (irq < 0)
    107			pr_err("error %d getting APIC IRQ %d\n", irq, data->index);
    108
    109		return irq;
    110	case X86_ACPI_IRQ_TYPE_GPIOINT:
    111		/* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */
    112		ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod);
    113		if (ret)
    114			return ret;
    115
    116		irq = gpiod_to_irq(gpiod);
    117		if (irq < 0) {
    118			pr_err("error %d getting IRQ %s %d\n", irq, data->chip, data->index);
    119			return irq;
    120		}
    121
    122		irq_type = acpi_dev_get_irq_type(data->trigger, data->polarity);
    123		if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq))
    124			irq_set_irq_type(irq, irq_type);
    125
    126		return irq;
    127	case X86_ACPI_IRQ_TYPE_PMIC:
    128		status = acpi_get_handle(NULL, data->chip, &handle);
    129		if (ACPI_FAILURE(status)) {
    130			pr_err("error could not get %s handle\n", data->chip);
    131			return -ENODEV;
    132		}
    133
    134		adev = acpi_fetch_acpi_dev(handle);
    135		if (!adev) {
    136			pr_err("error could not get %s adev\n", data->chip);
    137			return -ENODEV;
    138		}
    139
    140		fwspec.fwnode = acpi_fwnode_handle(adev);
    141		domain = irq_find_matching_fwspec(&fwspec, data->domain);
    142		if (!domain) {
    143			pr_err("error could not find IRQ domain for %s\n", data->chip);
    144			return -ENODEV;
    145		}
    146
    147		return irq_create_mapping(domain, data->index);
    148	default:
    149		return 0;
    150	}
    151}
    152
    153struct x86_i2c_client_info {
    154	struct i2c_board_info board_info;
    155	char *adapter_path;
    156	struct x86_acpi_irq_data irq_data;
    157};
    158
    159struct x86_serdev_info {
    160	const char *ctrl_hid;
    161	const char *ctrl_uid;
    162	const char *ctrl_devname;
    163	/*
    164	 * ATM the serdev core only supports of or ACPI matching; and sofar all
    165	 * Android x86 tablets DSDTs have usable serdev nodes, but sometimes
    166	 * under the wrong controller. So we just tie the existing serdev ACPI
    167	 * node to the right controller.
    168	 */
    169	const char *serdev_hid;
    170};
    171
    172struct x86_dev_info {
    173	char *invalid_aei_gpiochip;
    174	const char * const *modules;
    175	const struct software_node *bat_swnode;
    176	struct gpiod_lookup_table * const *gpiod_lookup_tables;
    177	const struct x86_i2c_client_info *i2c_client_info;
    178	const struct platform_device_info *pdev_info;
    179	const struct x86_serdev_info *serdev_info;
    180	int i2c_client_count;
    181	int pdev_count;
    182	int serdev_count;
    183	int (*init)(void);
    184	void (*exit)(void);
    185};
    186
    187/* Generic / shared charger / battery settings */
    188static const char * const tusb1211_chg_det_psy[] = { "tusb1211-charger-detect" };
    189static const char * const bq24190_psy[] = { "bq24190-charger" };
    190static const char * const bq25890_psy[] = { "bq25890-charger" };
    191
    192static const struct property_entry fg_bq24190_supply_props[] = {
    193	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
    194	{ }
    195};
    196
    197static const struct software_node fg_bq24190_supply_node = {
    198	.properties = fg_bq24190_supply_props,
    199};
    200
    201static const struct property_entry fg_bq25890_supply_props[] = {
    202	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_psy),
    203	{ }
    204};
    205
    206static const struct software_node fg_bq25890_supply_node = {
    207	.properties = fg_bq25890_supply_props,
    208};
    209
    210/* LiPo HighVoltage (max 4.35V) settings used by most devs with a HV bat. */
    211static const struct property_entry generic_lipo_hv_4v35_battery_props[] = {
    212	PROPERTY_ENTRY_STRING("compatible", "simple-battery"),
    213	PROPERTY_ENTRY_STRING("device-chemistry", "lithium-ion"),
    214	PROPERTY_ENTRY_U32("precharge-current-microamp", 256000),
    215	PROPERTY_ENTRY_U32("charge-term-current-microamp", 128000),
    216	PROPERTY_ENTRY_U32("constant-charge-current-max-microamp", 1856000),
    217	PROPERTY_ENTRY_U32("constant-charge-voltage-max-microvolt", 4352000),
    218	PROPERTY_ENTRY_U32("factory-internal-resistance-micro-ohms", 150000),
    219	{ }
    220};
    221
    222static const struct software_node generic_lipo_hv_4v35_battery_node = {
    223	.properties = generic_lipo_hv_4v35_battery_props,
    224};
    225
    226/* For enabling the bq24190 5V boost based on id-pin */
    227static struct regulator_consumer_supply intel_int3496_consumer = {
    228	.supply = "vbus",
    229	.dev_name = "intel-int3496",
    230};
    231
    232static const struct regulator_init_data bq24190_vbus_init_data = {
    233	.constraints = {
    234		.name = "bq24190_vbus",
    235		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
    236	},
    237	.consumer_supplies = &intel_int3496_consumer,
    238	.num_consumer_supplies = 1,
    239};
    240
    241static struct bq24190_platform_data bq24190_pdata = {
    242	.regulator_init_data = &bq24190_vbus_init_data,
    243};
    244
    245static const char * const bq24190_modules[] __initconst = {
    246	"intel_crystal_cove_charger", /* For the bq24190 IRQ */
    247	"bq24190_charger",            /* For the Vbus regulator for intel-int3496 */
    248	NULL
    249};
    250
    251/* Generic pdevs array and gpio-lookups for micro USB ID pin handling */
    252static const struct platform_device_info int3496_pdevs[] __initconst = {
    253	{
    254		/* For micro USB ID pin handling */
    255		.name = "intel-int3496",
    256		.id = PLATFORM_DEVID_NONE,
    257	},
    258};
    259
    260static struct gpiod_lookup_table int3496_gpo2_pin22_gpios = {
    261	.dev_id = "intel-int3496",
    262	.table = {
    263		GPIO_LOOKUP("INT33FC:02", 22, "id", GPIO_ACTIVE_HIGH),
    264		{ }
    265	},
    266};
    267
    268/* Asus ME176C and TF103C tablets shared data */
    269static struct gpio_keys_button asus_me176c_tf103c_lid = {
    270	.code = SW_LID,
    271	/* .gpio gets filled in by asus_me176c_tf103c_init() */
    272	.active_low = true,
    273	.desc = "lid_sw",
    274	.type = EV_SW,
    275	.wakeup = true,
    276	.debounce_interval = 50,
    277};
    278
    279static const struct gpio_keys_platform_data asus_me176c_tf103c_lid_pdata __initconst = {
    280	.buttons = &asus_me176c_tf103c_lid,
    281	.nbuttons = 1,
    282	.name = "lid_sw",
    283};
    284
    285static const struct platform_device_info asus_me176c_tf103c_pdevs[] __initconst = {
    286	{
    287		.name = "gpio-keys",
    288		.id = PLATFORM_DEVID_AUTO,
    289		.data = &asus_me176c_tf103c_lid_pdata,
    290		.size_data = sizeof(asus_me176c_tf103c_lid_pdata),
    291	},
    292	{
    293		/* For micro USB ID pin handling */
    294		.name = "intel-int3496",
    295		.id = PLATFORM_DEVID_NONE,
    296	},
    297};
    298
    299static int __init asus_me176c_tf103c_init(void)
    300{
    301	struct gpio_desc *gpiod;
    302	int ret;
    303
    304	ret = x86_android_tablet_get_gpiod("INT33FC:02", 12, &gpiod);
    305	if (ret < 0)
    306		return ret;
    307	asus_me176c_tf103c_lid.gpio = desc_to_gpio(gpiod);
    308
    309	return 0;
    310}
    311
    312
    313/* Asus ME176C tablets have an Android factory img with everything hardcoded */
    314static const char * const asus_me176c_accel_mount_matrix[] = {
    315	"-1", "0", "0",
    316	"0", "1", "0",
    317	"0", "0", "1"
    318};
    319
    320static const struct property_entry asus_me176c_accel_props[] = {
    321	PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", asus_me176c_accel_mount_matrix),
    322	{ }
    323};
    324
    325static const struct software_node asus_me176c_accel_node = {
    326	.properties = asus_me176c_accel_props,
    327};
    328
    329static const struct property_entry asus_me176c_bq24190_props[] = {
    330	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
    331	PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
    332	PROPERTY_ENTRY_U32("ti,system-minimum-microvolt", 3600000),
    333	PROPERTY_ENTRY_BOOL("omit-battery-class"),
    334	PROPERTY_ENTRY_BOOL("disable-reset"),
    335	{ }
    336};
    337
    338static const struct software_node asus_me176c_bq24190_node = {
    339	.properties = asus_me176c_bq24190_props,
    340};
    341
    342static const struct property_entry asus_me176c_ug3105_props[] = {
    343	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
    344	PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
    345	PROPERTY_ENTRY_U32("upisemi,rsns-microohm", 10000),
    346	{ }
    347};
    348
    349static const struct software_node asus_me176c_ug3105_node = {
    350	.properties = asus_me176c_ug3105_props,
    351};
    352
    353static const struct x86_i2c_client_info asus_me176c_i2c_clients[] __initconst = {
    354	{
    355		/* bq24297 battery charger */
    356		.board_info = {
    357			.type = "bq24190",
    358			.addr = 0x6b,
    359			.dev_name = "bq24297",
    360			.swnode = &asus_me176c_bq24190_node,
    361			.platform_data = &bq24190_pdata,
    362		},
    363		.adapter_path = "\\_SB_.I2C1",
    364		.irq_data = {
    365			.type = X86_ACPI_IRQ_TYPE_PMIC,
    366			.chip = "\\_SB_.I2C7.PMIC",
    367			.domain = DOMAIN_BUS_WAKEUP,
    368			.index = 0,
    369		},
    370	}, {
    371		/* ug3105 battery monitor */
    372		.board_info = {
    373			.type = "ug3105",
    374			.addr = 0x70,
    375			.dev_name = "ug3105",
    376			.swnode = &asus_me176c_ug3105_node,
    377		},
    378		.adapter_path = "\\_SB_.I2C1",
    379	}, {
    380		/* ak09911 compass */
    381		.board_info = {
    382			.type = "ak09911",
    383			.addr = 0x0c,
    384			.dev_name = "ak09911",
    385		},
    386		.adapter_path = "\\_SB_.I2C5",
    387	}, {
    388		/* kxtj21009 accel */
    389		.board_info = {
    390			.type = "kxtj21009",
    391			.addr = 0x0f,
    392			.dev_name = "kxtj21009",
    393			.swnode = &asus_me176c_accel_node,
    394		},
    395		.adapter_path = "\\_SB_.I2C5",
    396		.irq_data = {
    397			.type = X86_ACPI_IRQ_TYPE_APIC,
    398			.index = 0x44,
    399			.trigger = ACPI_EDGE_SENSITIVE,
    400			.polarity = ACPI_ACTIVE_LOW,
    401		},
    402	}, {
    403		/* goodix touchscreen */
    404		.board_info = {
    405			.type = "GDIX1001:00",
    406			.addr = 0x14,
    407			.dev_name = "goodix_ts",
    408		},
    409		.adapter_path = "\\_SB_.I2C6",
    410		.irq_data = {
    411			.type = X86_ACPI_IRQ_TYPE_APIC,
    412			.index = 0x45,
    413			.trigger = ACPI_EDGE_SENSITIVE,
    414			.polarity = ACPI_ACTIVE_LOW,
    415		},
    416	},
    417};
    418
    419static const struct x86_serdev_info asus_me176c_serdevs[] __initconst = {
    420	{
    421		.ctrl_hid = "80860F0A",
    422		.ctrl_uid = "2",
    423		.ctrl_devname = "serial0",
    424		.serdev_hid = "BCM2E3A",
    425	},
    426};
    427
    428static struct gpiod_lookup_table asus_me176c_goodix_gpios = {
    429	.dev_id = "i2c-goodix_ts",
    430	.table = {
    431		GPIO_LOOKUP("INT33FC:00", 60, "reset", GPIO_ACTIVE_HIGH),
    432		GPIO_LOOKUP("INT33FC:02", 28, "irq", GPIO_ACTIVE_HIGH),
    433		{ }
    434	},
    435};
    436
    437static struct gpiod_lookup_table * const asus_me176c_gpios[] = {
    438	&int3496_gpo2_pin22_gpios,
    439	&asus_me176c_goodix_gpios,
    440	NULL
    441};
    442
    443static const struct x86_dev_info asus_me176c_info __initconst = {
    444	.i2c_client_info = asus_me176c_i2c_clients,
    445	.i2c_client_count = ARRAY_SIZE(asus_me176c_i2c_clients),
    446	.pdev_info = asus_me176c_tf103c_pdevs,
    447	.pdev_count = ARRAY_SIZE(asus_me176c_tf103c_pdevs),
    448	.serdev_info = asus_me176c_serdevs,
    449	.serdev_count = ARRAY_SIZE(asus_me176c_serdevs),
    450	.gpiod_lookup_tables = asus_me176c_gpios,
    451	.bat_swnode = &generic_lipo_hv_4v35_battery_node,
    452	.modules = bq24190_modules,
    453	.invalid_aei_gpiochip = "INT33FC:02",
    454	.init = asus_me176c_tf103c_init,
    455};
    456
    457/* Asus TF103C tablets have an Android factory img with everything hardcoded */
    458static const char * const asus_tf103c_accel_mount_matrix[] = {
    459	"0", "-1", "0",
    460	"-1", "0", "0",
    461	"0", "0", "1"
    462};
    463
    464static const struct property_entry asus_tf103c_accel_props[] = {
    465	PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", asus_tf103c_accel_mount_matrix),
    466	{ }
    467};
    468
    469static const struct software_node asus_tf103c_accel_node = {
    470	.properties = asus_tf103c_accel_props,
    471};
    472
    473static const struct property_entry asus_tf103c_touchscreen_props[] = {
    474	PROPERTY_ENTRY_STRING("compatible", "atmel,atmel_mxt_ts"),
    475	{ }
    476};
    477
    478static const struct software_node asus_tf103c_touchscreen_node = {
    479	.properties = asus_tf103c_touchscreen_props,
    480};
    481
    482static const struct property_entry asus_tf103c_battery_props[] = {
    483	PROPERTY_ENTRY_STRING("compatible", "simple-battery"),
    484	PROPERTY_ENTRY_STRING("device-chemistry", "lithium-ion-polymer"),
    485	PROPERTY_ENTRY_U32("precharge-current-microamp", 256000),
    486	PROPERTY_ENTRY_U32("charge-term-current-microamp", 128000),
    487	PROPERTY_ENTRY_U32("constant-charge-current-max-microamp", 2048000),
    488	PROPERTY_ENTRY_U32("constant-charge-voltage-max-microvolt", 4208000),
    489	PROPERTY_ENTRY_U32("factory-internal-resistance-micro-ohms", 150000),
    490	{ }
    491};
    492
    493static const struct software_node asus_tf103c_battery_node = {
    494	.properties = asus_tf103c_battery_props,
    495};
    496
    497static const struct property_entry asus_tf103c_bq24190_props[] = {
    498	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
    499	PROPERTY_ENTRY_REF("monitored-battery", &asus_tf103c_battery_node),
    500	PROPERTY_ENTRY_U32("ti,system-minimum-microvolt", 3600000),
    501	PROPERTY_ENTRY_BOOL("omit-battery-class"),
    502	PROPERTY_ENTRY_BOOL("disable-reset"),
    503	{ }
    504};
    505
    506static const struct software_node asus_tf103c_bq24190_node = {
    507	.properties = asus_tf103c_bq24190_props,
    508};
    509
    510static const struct property_entry asus_tf103c_ug3105_props[] = {
    511	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
    512	PROPERTY_ENTRY_REF("monitored-battery", &asus_tf103c_battery_node),
    513	PROPERTY_ENTRY_U32("upisemi,rsns-microohm", 5000),
    514	{ }
    515};
    516
    517static const struct software_node asus_tf103c_ug3105_node = {
    518	.properties = asus_tf103c_ug3105_props,
    519};
    520
    521static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst = {
    522	{
    523		/* bq24297 battery charger */
    524		.board_info = {
    525			.type = "bq24190",
    526			.addr = 0x6b,
    527			.dev_name = "bq24297",
    528			.swnode = &asus_tf103c_bq24190_node,
    529			.platform_data = &bq24190_pdata,
    530		},
    531		.adapter_path = "\\_SB_.I2C1",
    532		.irq_data = {
    533			.type = X86_ACPI_IRQ_TYPE_PMIC,
    534			.chip = "\\_SB_.I2C7.PMIC",
    535			.domain = DOMAIN_BUS_WAKEUP,
    536			.index = 0,
    537		},
    538	}, {
    539		/* ug3105 battery monitor */
    540		.board_info = {
    541			.type = "ug3105",
    542			.addr = 0x70,
    543			.dev_name = "ug3105",
    544			.swnode = &asus_tf103c_ug3105_node,
    545		},
    546		.adapter_path = "\\_SB_.I2C1",
    547	}, {
    548		/* ak09911 compass */
    549		.board_info = {
    550			.type = "ak09911",
    551			.addr = 0x0c,
    552			.dev_name = "ak09911",
    553		},
    554		.adapter_path = "\\_SB_.I2C5",
    555	}, {
    556		/* kxtj21009 accel */
    557		.board_info = {
    558			.type = "kxtj21009",
    559			.addr = 0x0f,
    560			.dev_name = "kxtj21009",
    561			.swnode = &asus_tf103c_accel_node,
    562		},
    563		.adapter_path = "\\_SB_.I2C5",
    564	}, {
    565		/* atmel touchscreen */
    566		.board_info = {
    567			.type = "atmel_mxt_ts",
    568			.addr = 0x4a,
    569			.dev_name = "atmel_mxt_ts",
    570			.swnode = &asus_tf103c_touchscreen_node,
    571		},
    572		.adapter_path = "\\_SB_.I2C6",
    573		.irq_data = {
    574			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
    575			.chip = "INT33FC:02",
    576			.index = 28,
    577			.trigger = ACPI_EDGE_SENSITIVE,
    578			.polarity = ACPI_ACTIVE_LOW,
    579		},
    580	},
    581};
    582
    583static struct gpiod_lookup_table * const asus_tf103c_gpios[] = {
    584	&int3496_gpo2_pin22_gpios,
    585	NULL
    586};
    587
    588static const struct x86_dev_info asus_tf103c_info __initconst = {
    589	.i2c_client_info = asus_tf103c_i2c_clients,
    590	.i2c_client_count = ARRAY_SIZE(asus_tf103c_i2c_clients),
    591	.pdev_info = asus_me176c_tf103c_pdevs,
    592	.pdev_count = ARRAY_SIZE(asus_me176c_tf103c_pdevs),
    593	.gpiod_lookup_tables = asus_tf103c_gpios,
    594	.bat_swnode = &asus_tf103c_battery_node,
    595	.modules = bq24190_modules,
    596	.invalid_aei_gpiochip = "INT33FC:02",
    597	.init = asus_me176c_tf103c_init,
    598};
    599
    600/*
    601 * When booted with the BIOS set to Android mode the Chuwi Hi8 (CWI509) DSDT
    602 * contains a whole bunch of bogus ACPI I2C devices and is missing entries
    603 * for the touchscreen and the accelerometer.
    604 */
    605static const struct property_entry chuwi_hi8_gsl1680_props[] = {
    606	PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
    607	PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
    608	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
    609	PROPERTY_ENTRY_BOOL("silead,home-button"),
    610	PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"),
    611	{ }
    612};
    613
    614static const struct software_node chuwi_hi8_gsl1680_node = {
    615	.properties = chuwi_hi8_gsl1680_props,
    616};
    617
    618static const char * const chuwi_hi8_mount_matrix[] = {
    619	"1", "0", "0",
    620	"0", "-1", "0",
    621	"0", "0", "1"
    622};
    623
    624static const struct property_entry chuwi_hi8_bma250e_props[] = {
    625	PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", chuwi_hi8_mount_matrix),
    626	{ }
    627};
    628
    629static const struct software_node chuwi_hi8_bma250e_node = {
    630	.properties = chuwi_hi8_bma250e_props,
    631};
    632
    633static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = {
    634	{
    635		/* Silead touchscreen */
    636		.board_info = {
    637			.type = "gsl1680",
    638			.addr = 0x40,
    639			.swnode = &chuwi_hi8_gsl1680_node,
    640		},
    641		.adapter_path = "\\_SB_.I2C4",
    642		.irq_data = {
    643			.type = X86_ACPI_IRQ_TYPE_APIC,
    644			.index = 0x44,
    645			.trigger = ACPI_EDGE_SENSITIVE,
    646			.polarity = ACPI_ACTIVE_HIGH,
    647		},
    648	}, {
    649		/* BMA250E accelerometer */
    650		.board_info = {
    651			.type = "bma250e",
    652			.addr = 0x18,
    653			.swnode = &chuwi_hi8_bma250e_node,
    654		},
    655		.adapter_path = "\\_SB_.I2C3",
    656		.irq_data = {
    657			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
    658			.chip = "INT33FC:02",
    659			.index = 23,
    660			.trigger = ACPI_LEVEL_SENSITIVE,
    661			.polarity = ACPI_ACTIVE_HIGH,
    662		},
    663	},
    664};
    665
    666static const struct x86_dev_info chuwi_hi8_info __initconst = {
    667	.i2c_client_info = chuwi_hi8_i2c_clients,
    668	.i2c_client_count = ARRAY_SIZE(chuwi_hi8_i2c_clients),
    669};
    670
    671#define CZC_EC_EXTRA_PORT	0x68
    672#define CZC_EC_ANDROID_KEYS	0x63
    673
    674static int __init czc_p10t_init(void)
    675{
    676	/*
    677	 * The device boots up in "Windows 7" mode, when the home button sends a
    678	 * Windows specific key sequence (Left Meta + D) and the second button
    679	 * sends an unknown one while also toggling the Radio Kill Switch.
    680	 * This is a surprising behavior when the second button is labeled "Back".
    681	 *
    682	 * The vendor-supplied Android-x86 build switches the device to a "Android"
    683	 * mode by writing value 0x63 to the I/O port 0x68. This just seems to just
    684	 * set bit 6 on address 0x96 in the EC region; switching the bit directly
    685	 * seems to achieve the same result. It uses a "p10t_switcher" to do the
    686	 * job. It doesn't seem to be able to do anything else, and no other use
    687	 * of the port 0x68 is known.
    688	 *
    689	 * In the Android mode, the home button sends just a single scancode,
    690	 * which can be handled in Linux userspace more reasonably and the back
    691	 * button only sends a scancode without toggling the kill switch.
    692	 * The scancode can then be mapped either to Back or RF Kill functionality
    693	 * in userspace, depending on how the button is labeled on that particular
    694	 * model.
    695	 */
    696	outb(CZC_EC_ANDROID_KEYS, CZC_EC_EXTRA_PORT);
    697	return 0;
    698}
    699
    700static const struct x86_dev_info czc_p10t __initconst = {
    701	.init = czc_p10t_init,
    702};
    703
    704/* Lenovo Yoga Book X90F / X91F / X91L need manual instantiation of the fg client */
    705static const struct x86_i2c_client_info lenovo_yogabook_x9x_i2c_clients[] __initconst = {
    706	{
    707		/* BQ27542 fuel-gauge */
    708		.board_info = {
    709			.type = "bq27542",
    710			.addr = 0x55,
    711			.dev_name = "bq27542",
    712			.swnode = &fg_bq25890_supply_node,
    713		},
    714		.adapter_path = "\\_SB_.PCI0.I2C1",
    715	},
    716};
    717
    718static const struct x86_dev_info lenovo_yogabook_x9x_info __initconst = {
    719	.i2c_client_info = lenovo_yogabook_x9x_i2c_clients,
    720	.i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x9x_i2c_clients),
    721};
    722
    723/* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */
    724static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
    725	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
    726	PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
    727	PROPERTY_ENTRY_BOOL("omit-battery-class"),
    728	PROPERTY_ENTRY_BOOL("disable-reset"),
    729	{ }
    730};
    731
    732static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
    733	.properties = lenovo_yoga_tab2_830_1050_bq24190_props,
    734};
    735
    736/* This gets filled by lenovo_yoga_tab2_830_1050_init() */
    737static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
    738
    739static struct lp855x_platform_data lenovo_yoga_tab2_830_1050_lp8557_pdata = {
    740	.device_control = 0x86,
    741	.initial_brightness = 128,
    742};
    743
    744static const struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initconst = {
    745	{
    746		/* bq24292i battery charger */
    747		.board_info = {
    748			.type = "bq24190",
    749			.addr = 0x6b,
    750			.dev_name = "bq24292i",
    751			.swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
    752			.platform_data = &bq24190_pdata,
    753		},
    754		.adapter_path = "\\_SB_.I2C1",
    755		.irq_data = {
    756			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
    757			.chip = "INT33FC:02",
    758			.index = 2,
    759			.trigger = ACPI_EDGE_SENSITIVE,
    760			.polarity = ACPI_ACTIVE_HIGH,
    761		},
    762	}, {
    763		/* BQ27541 fuel-gauge */
    764		.board_info = {
    765			.type = "bq27541",
    766			.addr = 0x55,
    767			.dev_name = "bq27541",
    768			.swnode = &fg_bq24190_supply_node,
    769		},
    770		.adapter_path = "\\_SB_.I2C1",
    771	}, {
    772		/* Synaptics RMI touchscreen */
    773		.board_info = {
    774			.type = "rmi4_i2c",
    775			.addr = 0x38,
    776			.dev_name = "rmi4_i2c",
    777			.platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
    778		},
    779		.adapter_path = "\\_SB_.I2C6",
    780		.irq_data = {
    781			.type = X86_ACPI_IRQ_TYPE_APIC,
    782			.index = 0x45,
    783			.trigger = ACPI_EDGE_SENSITIVE,
    784			.polarity = ACPI_ACTIVE_HIGH,
    785		},
    786	}, {
    787		/* LP8557 Backlight controller */
    788		.board_info = {
    789			.type = "lp8557",
    790			.addr = 0x2c,
    791			.dev_name = "lp8557",
    792			.platform_data = &lenovo_yoga_tab2_830_1050_lp8557_pdata,
    793		},
    794		.adapter_path = "\\_SB_.I2C3",
    795	},
    796};
    797
    798static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
    799	.dev_id = "intel-int3496",
    800	.table = {
    801		GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
    802		GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
    803		{ }
    804	},
    805};
    806
    807#define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
    808
    809static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = {
    810	.dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME,
    811	.table = {
    812		GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH),
    813		GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH),
    814		GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
    815		GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW),
    816		{ }
    817	},
    818};
    819
    820static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = {
    821	&lenovo_yoga_tab2_830_1050_int3496_gpios,
    822	&lenovo_yoga_tab2_830_1050_codec_gpios,
    823	NULL
    824};
    825
    826static int __init lenovo_yoga_tab2_830_1050_init(void);
    827static void lenovo_yoga_tab2_830_1050_exit(void);
    828
    829static struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initdata = {
    830	.i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
    831	/* i2c_client_count gets set by lenovo_yoga_tab2_830_1050_init() */
    832	.pdev_info = int3496_pdevs,
    833	.pdev_count = ARRAY_SIZE(int3496_pdevs),
    834	.gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
    835	.bat_swnode = &generic_lipo_hv_4v35_battery_node,
    836	.modules = bq24190_modules,
    837	.invalid_aei_gpiochip = "INT33FC:02",
    838	.init = lenovo_yoga_tab2_830_1050_init,
    839	.exit = lenovo_yoga_tab2_830_1050_exit,
    840};
    841
    842/*
    843 * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same
    844 * mainboard, but they need some different treatment related to the display:
    845 * 1. The 830 uses a portrait LCD panel with a landscape touchscreen, requiring
    846 *    the touchscreen driver to adjust the touch-coords to match the LCD.
    847 * 2. Both use an TI LP8557 LED backlight controller. On the 1050 the LP8557's
    848 *    PWM input is connected to the PMIC's PWM output and everything works fine
    849 *    with the defaults programmed into the LP8557 by the BIOS.
    850 *    But on the 830 the LP8557's PWM input is connected to a PWM output coming
    851 *    from the LCD panel's controller. The Android code has a hack in the i915
    852 *    driver to write the non-standard DSI reg 0x9f with the desired backlight
    853 *    level to set the duty-cycle of the LCD's PWM output.
    854 *
    855 *    To avoid having to have a similar hack in the mainline kernel the LP8557
    856 *    entry in lenovo_yoga_tab2_830_1050_i2c_clients instead just programs the
    857 *    LP8557 to directly set the level, ignoring the PWM input. This means that
    858 *    the LP8557 i2c_client should only be instantiated on the 830.
    859 */
    860static int __init lenovo_yoga_tab2_830_1050_init_display(void)
    861{
    862	struct gpio_desc *gpiod;
    863	int ret;
    864
    865	/* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
    866	ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod);
    867	if (ret)
    868		return ret;
    869
    870	ret = gpiod_get_value_cansleep(gpiod);
    871	if (ret) {
    872		pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
    873		lenovo_yoga_tab2_830_1050_info.i2c_client_count =
    874			ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients) - 1;
    875	} else {
    876		pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
    877		lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
    878		lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
    879		lenovo_yoga_tab2_830_1050_info.i2c_client_count =
    880			ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients);
    881	}
    882
    883	return 0;
    884}
    885
    886/* SUS (INT33FC:02) pin 6 needs to be configured as pmu_clk for the audio codec */
    887static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map =
    888	PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk",
    889			  "INT33FC:02", "pmu_clk2_grp", "pmu_clk");
    890
    891static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
    892
    893static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
    894{
    895	struct device *codec_dev;
    896	struct pinctrl *pinctrl;
    897	int ret;
    898
    899	codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
    900					    LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
    901	if (!codec_dev) {
    902		pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
    903		return -ENODEV;
    904	}
    905
    906	ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
    907	if (ret)
    908		goto err_put_device;
    909
    910	pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk");
    911	if (IS_ERR(pinctrl)) {
    912		ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n");
    913		goto err_unregister_mappings;
    914	}
    915
    916	/* We're done with the codec_dev now */
    917	put_device(codec_dev);
    918
    919	lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
    920	return 0;
    921
    922err_unregister_mappings:
    923	pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
    924err_put_device:
    925	put_device(codec_dev);
    926	return ret;
    927}
    928
    929/*
    930 * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off
    931 * gets used as pm_power_off handler. This causes "poweroff" on these tablets
    932 * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice*
    933 * followed by a normal 3 second press to recover. Avoid this by doing an EFI
    934 * poweroff instead.
    935 */
    936static void lenovo_yoga_tab2_830_1050_power_off(void)
    937{
    938	efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
    939}
    940
    941static int __init lenovo_yoga_tab2_830_1050_init(void)
    942{
    943	int ret;
    944
    945	ret = lenovo_yoga_tab2_830_1050_init_display();
    946	if (ret)
    947		return ret;
    948
    949	ret = lenovo_yoga_tab2_830_1050_init_codec();
    950	if (ret)
    951		return ret;
    952
    953	pm_power_off = lenovo_yoga_tab2_830_1050_power_off;
    954	return 0;
    955}
    956
    957static void lenovo_yoga_tab2_830_1050_exit(void)
    958{
    959	pm_power_off = NULL; /* Just turn poweroff into halt on module unload */
    960
    961	if (lenovo_yoga_tab2_830_1050_codec_pinctrl) {
    962		pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
    963		pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
    964	}
    965}
    966
    967/* Nextbook Ares 8 tablets have an Android factory img with everything hardcoded */
    968static const char * const nextbook_ares8_accel_mount_matrix[] = {
    969	"0", "-1", "0",
    970	"-1", "0", "0",
    971	"0", "0", "1"
    972};
    973
    974static const struct property_entry nextbook_ares8_accel_props[] = {
    975	PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", nextbook_ares8_accel_mount_matrix),
    976	{ }
    977};
    978
    979static const struct software_node nextbook_ares8_accel_node = {
    980	.properties = nextbook_ares8_accel_props,
    981};
    982
    983static const struct property_entry nextbook_ares8_touchscreen_props[] = {
    984	PROPERTY_ENTRY_U32("touchscreen-size-x", 800),
    985	PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
    986	{ }
    987};
    988
    989static const struct software_node nextbook_ares8_touchscreen_node = {
    990	.properties = nextbook_ares8_touchscreen_props,
    991};
    992
    993static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst = {
    994	{
    995		/* Freescale MMA8653FC accel */
    996		.board_info = {
    997			.type = "mma8653",
    998			.addr = 0x1d,
    999			.dev_name = "mma8653",
   1000			.swnode = &nextbook_ares8_accel_node,
   1001		},
   1002		.adapter_path = "\\_SB_.I2C3",
   1003	}, {
   1004		/* FT5416DQ9 touchscreen controller */
   1005		.board_info = {
   1006			.type = "edt-ft5x06",
   1007			.addr = 0x38,
   1008			.dev_name = "ft5416",
   1009			.swnode = &nextbook_ares8_touchscreen_node,
   1010		},
   1011		.adapter_path = "\\_SB_.I2C4",
   1012		.irq_data = {
   1013			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
   1014			.chip = "INT33FC:02",
   1015			.index = 3,
   1016			.trigger = ACPI_EDGE_SENSITIVE,
   1017			.polarity = ACPI_ACTIVE_LOW,
   1018		},
   1019	},
   1020};
   1021
   1022static struct gpiod_lookup_table nextbook_ares8_int3496_gpios = {
   1023	.dev_id = "intel-int3496",
   1024	.table = {
   1025		GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_HIGH),
   1026		GPIO_LOOKUP("INT33FC:02", 18, "id", GPIO_ACTIVE_HIGH),
   1027		{ }
   1028	},
   1029};
   1030
   1031static struct gpiod_lookup_table * const nextbook_ares8_gpios[] = {
   1032	&nextbook_ares8_int3496_gpios,
   1033	NULL
   1034};
   1035
   1036static const struct x86_dev_info nextbook_ares8_info __initconst = {
   1037	.i2c_client_info = nextbook_ares8_i2c_clients,
   1038	.i2c_client_count = ARRAY_SIZE(nextbook_ares8_i2c_clients),
   1039	.pdev_info = int3496_pdevs,
   1040	.pdev_count = ARRAY_SIZE(int3496_pdevs),
   1041	.gpiod_lookup_tables = nextbook_ares8_gpios,
   1042	.invalid_aei_gpiochip = "INT33FC:02",
   1043};
   1044
   1045/*
   1046 * Whitelabel (sold as various brands) TM800A550L tablets.
   1047 * These tablet's DSDT contains a whole bunch of bogus ACPI I2C devices
   1048 * (removed through acpi_quirk_skip_i2c_client_enumeration()) and
   1049 * the touchscreen fwnode has the wrong GPIOs.
   1050 */
   1051static const char * const whitelabel_tm800a550l_accel_mount_matrix[] = {
   1052	"-1", "0", "0",
   1053	"0", "1", "0",
   1054	"0", "0", "1"
   1055};
   1056
   1057static const struct property_entry whitelabel_tm800a550l_accel_props[] = {
   1058	PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", whitelabel_tm800a550l_accel_mount_matrix),
   1059	{ }
   1060};
   1061
   1062static const struct software_node whitelabel_tm800a550l_accel_node = {
   1063	.properties = whitelabel_tm800a550l_accel_props,
   1064};
   1065
   1066static const struct property_entry whitelabel_tm800a550l_goodix_props[] = {
   1067	PROPERTY_ENTRY_STRING("firmware-name", "gt912-tm800a550l.fw"),
   1068	PROPERTY_ENTRY_STRING("goodix,config-name", "gt912-tm800a550l.cfg"),
   1069	PROPERTY_ENTRY_U32("goodix,main-clk", 54),
   1070	{ }
   1071};
   1072
   1073static const struct software_node whitelabel_tm800a550l_goodix_node = {
   1074	.properties = whitelabel_tm800a550l_goodix_props,
   1075};
   1076
   1077static const struct x86_i2c_client_info whitelabel_tm800a550l_i2c_clients[] __initconst = {
   1078	{
   1079		/* goodix touchscreen */
   1080		.board_info = {
   1081			.type = "GDIX1001:00",
   1082			.addr = 0x14,
   1083			.dev_name = "goodix_ts",
   1084			.swnode = &whitelabel_tm800a550l_goodix_node,
   1085		},
   1086		.adapter_path = "\\_SB_.I2C2",
   1087		.irq_data = {
   1088			.type = X86_ACPI_IRQ_TYPE_APIC,
   1089			.index = 0x44,
   1090			.trigger = ACPI_EDGE_SENSITIVE,
   1091			.polarity = ACPI_ACTIVE_HIGH,
   1092		},
   1093	}, {
   1094		/* kxcj91008 accel */
   1095		.board_info = {
   1096			.type = "kxcj91008",
   1097			.addr = 0x0f,
   1098			.dev_name = "kxcj91008",
   1099			.swnode = &whitelabel_tm800a550l_accel_node,
   1100		},
   1101		.adapter_path = "\\_SB_.I2C3",
   1102	},
   1103};
   1104
   1105static struct gpiod_lookup_table whitelabel_tm800a550l_goodix_gpios = {
   1106	.dev_id = "i2c-goodix_ts",
   1107	.table = {
   1108		GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_HIGH),
   1109		GPIO_LOOKUP("INT33FC:02", 3, "irq", GPIO_ACTIVE_HIGH),
   1110		{ }
   1111	},
   1112};
   1113
   1114static struct gpiod_lookup_table * const whitelabel_tm800a550l_gpios[] = {
   1115	&whitelabel_tm800a550l_goodix_gpios,
   1116	NULL
   1117};
   1118
   1119static const struct x86_dev_info whitelabel_tm800a550l_info __initconst = {
   1120	.i2c_client_info = whitelabel_tm800a550l_i2c_clients,
   1121	.i2c_client_count = ARRAY_SIZE(whitelabel_tm800a550l_i2c_clients),
   1122	.gpiod_lookup_tables = whitelabel_tm800a550l_gpios,
   1123};
   1124
   1125/*
   1126 * If the EFI bootloader is not Xiaomi's own signed Android loader, then the
   1127 * Xiaomi Mi Pad 2 X86 tablet sets OSID in the DSDT to 1 (Windows), causing
   1128 * a bunch of devices to be hidden.
   1129 *
   1130 * This takes care of instantiating the hidden devices manually.
   1131 */
   1132static const struct x86_i2c_client_info xiaomi_mipad2_i2c_clients[] __initconst = {
   1133	{
   1134		/* BQ27520 fuel-gauge */
   1135		.board_info = {
   1136			.type = "bq27520",
   1137			.addr = 0x55,
   1138			.dev_name = "bq27520",
   1139			.swnode = &fg_bq25890_supply_node,
   1140		},
   1141		.adapter_path = "\\_SB_.PCI0.I2C1",
   1142	}, {
   1143		/* KTD2026 RGB notification LED controller */
   1144		.board_info = {
   1145			.type = "ktd2026",
   1146			.addr = 0x30,
   1147			.dev_name = "ktd2026",
   1148		},
   1149		.adapter_path = "\\_SB_.PCI0.I2C3",
   1150	},
   1151};
   1152
   1153static const struct x86_dev_info xiaomi_mipad2_info __initconst = {
   1154	.i2c_client_info = xiaomi_mipad2_i2c_clients,
   1155	.i2c_client_count = ARRAY_SIZE(xiaomi_mipad2_i2c_clients),
   1156};
   1157
   1158static const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
   1159	{
   1160		/* Asus MeMO Pad 7 ME176C */
   1161		.matches = {
   1162			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
   1163			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
   1164		},
   1165		.driver_data = (void *)&asus_me176c_info,
   1166	},
   1167	{
   1168		/* Asus TF103C */
   1169		.matches = {
   1170			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
   1171			DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
   1172		},
   1173		.driver_data = (void *)&asus_tf103c_info,
   1174	},
   1175	{
   1176		/* Chuwi Hi8 (CWI509) */
   1177		.matches = {
   1178			DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
   1179			DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"),
   1180			DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
   1181			DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
   1182		},
   1183		.driver_data = (void *)&chuwi_hi8_info,
   1184	},
   1185	{
   1186		/* CZC P10T */
   1187		.ident = "CZC ODEON TPC-10 (\"P10T\")",
   1188		.matches = {
   1189			DMI_MATCH(DMI_SYS_VENDOR, "CZC"),
   1190			DMI_MATCH(DMI_PRODUCT_NAME, "ODEON*TPC-10"),
   1191		},
   1192		.driver_data = (void *)&czc_p10t,
   1193	},
   1194	{
   1195		/* CZC P10T variant */
   1196		.ident = "ViewSonic ViewPad 10",
   1197		.matches = {
   1198			DMI_MATCH(DMI_SYS_VENDOR, "ViewSonic"),
   1199			DMI_MATCH(DMI_PRODUCT_NAME, "VPAD10"),
   1200		},
   1201		.driver_data = (void *)&czc_p10t,
   1202	},
   1203	{
   1204		/* Lenovo Yoga Book X90F / X91F / X91L */
   1205		.matches = {
   1206			/* Non exact match to match all versions */
   1207			DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
   1208		},
   1209		.driver_data = (void *)&lenovo_yogabook_x9x_info,
   1210	},
   1211	{
   1212		/*
   1213		 * Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10"
   1214		 * Lenovo Yoga Tablet 2 use the same mainboard)
   1215		 */
   1216		.matches = {
   1217			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
   1218			DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
   1219			DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
   1220			/* Partial match on beginning of BIOS version */
   1221			DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
   1222		},
   1223		.driver_data = (void *)&lenovo_yoga_tab2_830_1050_info,
   1224	},
   1225	{
   1226		/* Nextbook Ares 8 */
   1227		.matches = {
   1228			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
   1229			DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
   1230		},
   1231		.driver_data = (void *)&nextbook_ares8_info,
   1232	},
   1233	{
   1234		/* Whitelabel (sold as various brands) TM800A550L */
   1235		.matches = {
   1236			DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
   1237			DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
   1238			/* Above strings are too generic, also match on BIOS version */
   1239			DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
   1240		},
   1241		.driver_data = (void *)&whitelabel_tm800a550l_info,
   1242	},
   1243	{
   1244		/* Xiaomi Mi Pad 2 */
   1245		.matches = {
   1246			DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
   1247			DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
   1248		},
   1249		.driver_data = (void *)&xiaomi_mipad2_info,
   1250	},
   1251	{ }
   1252};
   1253MODULE_DEVICE_TABLE(dmi, x86_android_tablet_ids);
   1254
   1255static int i2c_client_count;
   1256static int pdev_count;
   1257static int serdev_count;
   1258static struct i2c_client **i2c_clients;
   1259static struct platform_device **pdevs;
   1260static struct serdev_device **serdevs;
   1261static struct gpiod_lookup_table * const *gpiod_lookup_tables;
   1262static const struct software_node *bat_swnode;
   1263static void (*exit_handler)(void);
   1264
   1265static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info,
   1266					     int idx)
   1267{
   1268	const struct x86_i2c_client_info *client_info = &dev_info->i2c_client_info[idx];
   1269	struct i2c_board_info board_info = client_info->board_info;
   1270	struct i2c_adapter *adap;
   1271	acpi_handle handle;
   1272	acpi_status status;
   1273
   1274	board_info.irq = x86_acpi_irq_helper_get(&client_info->irq_data);
   1275	if (board_info.irq < 0)
   1276		return board_info.irq;
   1277
   1278	status = acpi_get_handle(NULL, client_info->adapter_path, &handle);
   1279	if (ACPI_FAILURE(status)) {
   1280		pr_err("Error could not get %s handle\n", client_info->adapter_path);
   1281		return -ENODEV;
   1282	}
   1283
   1284	adap = i2c_acpi_find_adapter_by_handle(handle);
   1285	if (!adap) {
   1286		pr_err("error could not get %s adapter\n", client_info->adapter_path);
   1287		return -ENODEV;
   1288	}
   1289
   1290	i2c_clients[idx] = i2c_new_client_device(adap, &board_info);
   1291	put_device(&adap->dev);
   1292	if (IS_ERR(i2c_clients[idx]))
   1293		return dev_err_probe(&adap->dev, PTR_ERR(i2c_clients[idx]),
   1294				      "creating I2C-client %d\n", idx);
   1295
   1296	return 0;
   1297}
   1298
   1299static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx)
   1300{
   1301	struct acpi_device *ctrl_adev, *serdev_adev;
   1302	struct serdev_device *serdev;
   1303	struct device *ctrl_dev;
   1304	int ret = -ENODEV;
   1305
   1306	ctrl_adev = acpi_dev_get_first_match_dev(info->ctrl_hid, info->ctrl_uid, -1);
   1307	if (!ctrl_adev) {
   1308		pr_err("error could not get %s/%s ctrl adev\n",
   1309		       info->ctrl_hid, info->ctrl_uid);
   1310		return -ENODEV;
   1311	}
   1312
   1313	serdev_adev = acpi_dev_get_first_match_dev(info->serdev_hid, NULL, -1);
   1314	if (!serdev_adev) {
   1315		pr_err("error could not get %s serdev adev\n", info->serdev_hid);
   1316		goto put_ctrl_adev;
   1317	}
   1318
   1319	/* get_first_physical_node() returns a weak ref, no need to put() it */
   1320	ctrl_dev = acpi_get_first_physical_node(ctrl_adev);
   1321	if (!ctrl_dev)	{
   1322		pr_err("error could not get %s/%s ctrl physical dev\n",
   1323		       info->ctrl_hid, info->ctrl_uid);
   1324		goto put_serdev_adev;
   1325	}
   1326
   1327	/* ctrl_dev now points to the controller's parent, get the controller */
   1328	ctrl_dev = device_find_child_by_name(ctrl_dev, info->ctrl_devname);
   1329	if (!ctrl_dev) {
   1330		pr_err("error could not get %s/%s %s ctrl dev\n",
   1331		       info->ctrl_hid, info->ctrl_uid, info->ctrl_devname);
   1332		goto put_serdev_adev;
   1333	}
   1334
   1335	serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev));
   1336	if (!serdev) {
   1337		ret = -ENOMEM;
   1338		goto put_serdev_adev;
   1339	}
   1340
   1341	ACPI_COMPANION_SET(&serdev->dev, serdev_adev);
   1342	acpi_device_set_enumerated(serdev_adev);
   1343
   1344	ret = serdev_device_add(serdev);
   1345	if (ret) {
   1346		dev_err(&serdev->dev, "error %d adding serdev\n", ret);
   1347		serdev_device_put(serdev);
   1348		goto put_serdev_adev;
   1349	}
   1350
   1351	serdevs[idx] = serdev;
   1352
   1353put_serdev_adev:
   1354	acpi_dev_put(serdev_adev);
   1355put_ctrl_adev:
   1356	acpi_dev_put(ctrl_adev);
   1357	return ret;
   1358}
   1359
   1360static void x86_android_tablet_cleanup(void)
   1361{
   1362	int i;
   1363
   1364	for (i = 0; i < serdev_count; i++) {
   1365		if (serdevs[i])
   1366			serdev_device_remove(serdevs[i]);
   1367	}
   1368
   1369	kfree(serdevs);
   1370
   1371	for (i = 0; i < pdev_count; i++)
   1372		platform_device_unregister(pdevs[i]);
   1373
   1374	kfree(pdevs);
   1375
   1376	for (i = 0; i < i2c_client_count; i++)
   1377		i2c_unregister_device(i2c_clients[i]);
   1378
   1379	kfree(i2c_clients);
   1380
   1381	if (exit_handler)
   1382		exit_handler();
   1383
   1384	for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
   1385		gpiod_remove_lookup_table(gpiod_lookup_tables[i]);
   1386
   1387	software_node_unregister(bat_swnode);
   1388}
   1389
   1390static __init int x86_android_tablet_init(void)
   1391{
   1392	const struct x86_dev_info *dev_info;
   1393	const struct dmi_system_id *id;
   1394	struct gpio_chip *chip;
   1395	int i, ret = 0;
   1396
   1397	id = dmi_first_match(x86_android_tablet_ids);
   1398	if (!id)
   1399		return -ENODEV;
   1400
   1401	dev_info = id->driver_data;
   1402
   1403	/*
   1404	 * The broken DSDTs on these devices often also include broken
   1405	 * _AEI (ACPI Event Interrupt) handlers, disable these.
   1406	 */
   1407	if (dev_info->invalid_aei_gpiochip) {
   1408		chip = gpiochip_find(dev_info->invalid_aei_gpiochip,
   1409				     gpiochip_find_match_label);
   1410		if (!chip) {
   1411			pr_err("error cannot find GPIO chip %s\n", dev_info->invalid_aei_gpiochip);
   1412			return -ENODEV;
   1413		}
   1414		acpi_gpiochip_free_interrupts(chip);
   1415	}
   1416
   1417	/*
   1418	 * Since this runs from module_init() it cannot use -EPROBE_DEFER,
   1419	 * instead pre-load any modules which are listed as requirements.
   1420	 */
   1421	for (i = 0; dev_info->modules && dev_info->modules[i]; i++)
   1422		request_module(dev_info->modules[i]);
   1423
   1424	bat_swnode = dev_info->bat_swnode;
   1425	if (bat_swnode) {
   1426		ret = software_node_register(bat_swnode);
   1427		if (ret)
   1428			return ret;
   1429	}
   1430
   1431	gpiod_lookup_tables = dev_info->gpiod_lookup_tables;
   1432	for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
   1433		gpiod_add_lookup_table(gpiod_lookup_tables[i]);
   1434
   1435	if (dev_info->init) {
   1436		ret = dev_info->init();
   1437		if (ret < 0) {
   1438			x86_android_tablet_cleanup();
   1439			return ret;
   1440		}
   1441		exit_handler = dev_info->exit;
   1442	}
   1443
   1444	i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL);
   1445	if (!i2c_clients) {
   1446		x86_android_tablet_cleanup();
   1447		return -ENOMEM;
   1448	}
   1449
   1450	i2c_client_count = dev_info->i2c_client_count;
   1451	for (i = 0; i < i2c_client_count; i++) {
   1452		ret = x86_instantiate_i2c_client(dev_info, i);
   1453		if (ret < 0) {
   1454			x86_android_tablet_cleanup();
   1455			return ret;
   1456		}
   1457	}
   1458
   1459	pdevs = kcalloc(dev_info->pdev_count, sizeof(*pdevs), GFP_KERNEL);
   1460	if (!pdevs) {
   1461		x86_android_tablet_cleanup();
   1462		return -ENOMEM;
   1463	}
   1464
   1465	pdev_count = dev_info->pdev_count;
   1466	for (i = 0; i < pdev_count; i++) {
   1467		pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]);
   1468		if (IS_ERR(pdevs[i])) {
   1469			x86_android_tablet_cleanup();
   1470			return PTR_ERR(pdevs[i]);
   1471		}
   1472	}
   1473
   1474	serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL);
   1475	if (!serdevs) {
   1476		x86_android_tablet_cleanup();
   1477		return -ENOMEM;
   1478	}
   1479
   1480	serdev_count = dev_info->serdev_count;
   1481	for (i = 0; i < serdev_count; i++) {
   1482		ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i);
   1483		if (ret < 0) {
   1484			x86_android_tablet_cleanup();
   1485			return ret;
   1486		}
   1487	}
   1488
   1489	return 0;
   1490}
   1491
   1492module_init(x86_android_tablet_init);
   1493module_exit(x86_android_tablet_cleanup);
   1494
   1495MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
   1496MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver");
   1497MODULE_LICENSE("GPL");