162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Board info for Lenovo X86 tablets which ship with Android as the factory image 462306a36Sopenharmony_ci * and which have broken DSDT tables. The factory kernels shipped on these 562306a36Sopenharmony_ci * devices typically have a bunch of things hardcoded, rather than specified 662306a36Sopenharmony_ci * in their DSDT. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/efi.h> 1462306a36Sopenharmony_ci#include <linux/gpio/machine.h> 1562306a36Sopenharmony_ci#include <linux/mfd/intel_soc_pmic.h> 1662306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h> 1762306a36Sopenharmony_ci#include <linux/pinctrl/machine.h> 1862306a36Sopenharmony_ci#include <linux/platform_data/lp855x.h> 1962306a36Sopenharmony_ci#include <linux/platform_device.h> 2062306a36Sopenharmony_ci#include <linux/reboot.h> 2162306a36Sopenharmony_ci#include <linux/rmi.h> 2262306a36Sopenharmony_ci#include <linux/spi/spi.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "shared-psy-info.h" 2562306a36Sopenharmony_ci#include "x86-android-tablets.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* 2862306a36Sopenharmony_ci * Various Lenovo models use a TI LP8557 LED backlight controller with its PWM 2962306a36Sopenharmony_ci * input connected to a PWM output coming from the LCD panel's controller. 3062306a36Sopenharmony_ci * The Android kernels have a hack in the i915 driver to write a non-standard 3162306a36Sopenharmony_ci * panel specific DSI register to set the duty-cycle of the LCD's PWM output. 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * To avoid having to have a similar hack in the mainline kernel program the 3462306a36Sopenharmony_ci * LP8557 to directly set the level and use the lp855x_bl driver for control. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_cistatic struct lp855x_platform_data lenovo_lp8557_pdata = { 3762306a36Sopenharmony_ci .device_control = 0x86, 3862306a36Sopenharmony_ci .initial_brightness = 128, 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* Lenovo Yoga Book X90F / X90L's Android factory img has everything hardcoded */ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic const struct property_entry lenovo_yb1_x90_wacom_props[] = { 4462306a36Sopenharmony_ci PROPERTY_ENTRY_U32("hid-descr-addr", 0x0001), 4562306a36Sopenharmony_ci PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 150), 4662306a36Sopenharmony_ci { } 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const struct software_node lenovo_yb1_x90_wacom_node = { 5062306a36Sopenharmony_ci .properties = lenovo_yb1_x90_wacom_props, 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* 5462306a36Sopenharmony_ci * The HiDeep IST940E touchscreen comes up in I2C-HID mode. The native protocol 5562306a36Sopenharmony_ci * reports ABS_MT_PRESSURE and ABS_MT_TOUCH_MAJOR which are not reported in HID 5662306a36Sopenharmony_ci * mode, so using native mode is preferred. 5762306a36Sopenharmony_ci * It could alternatively be used in HID mode by changing the properties to: 5862306a36Sopenharmony_ci * PROPERTY_ENTRY_U32("hid-descr-addr", 0x0020), 5962306a36Sopenharmony_ci * PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120), 6062306a36Sopenharmony_ci * and changing board_info.type to "hid-over-i2c". 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_cistatic const struct property_entry lenovo_yb1_x90_hideep_ts_props[] = { 6362306a36Sopenharmony_ci PROPERTY_ENTRY_U32("touchscreen-size-x", 1200), 6462306a36Sopenharmony_ci PROPERTY_ENTRY_U32("touchscreen-size-y", 1920), 6562306a36Sopenharmony_ci PROPERTY_ENTRY_U32("touchscreen-max-pressure", 16384), 6662306a36Sopenharmony_ci PROPERTY_ENTRY_BOOL("hideep,force-native-protocol"), 6762306a36Sopenharmony_ci { } 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic const struct software_node lenovo_yb1_x90_hideep_ts_node = { 7162306a36Sopenharmony_ci .properties = lenovo_yb1_x90_hideep_ts_props, 7262306a36Sopenharmony_ci}; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst = { 7562306a36Sopenharmony_ci { 7662306a36Sopenharmony_ci /* BQ27542 fuel-gauge */ 7762306a36Sopenharmony_ci .board_info = { 7862306a36Sopenharmony_ci .type = "bq27542", 7962306a36Sopenharmony_ci .addr = 0x55, 8062306a36Sopenharmony_ci .dev_name = "bq27542", 8162306a36Sopenharmony_ci .swnode = &fg_bq25890_supply_node, 8262306a36Sopenharmony_ci }, 8362306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C1", 8462306a36Sopenharmony_ci }, { 8562306a36Sopenharmony_ci /* Goodix Touchscreen in keyboard half */ 8662306a36Sopenharmony_ci .board_info = { 8762306a36Sopenharmony_ci .type = "GDIX1001:00", 8862306a36Sopenharmony_ci .addr = 0x14, 8962306a36Sopenharmony_ci .dev_name = "goodix_ts", 9062306a36Sopenharmony_ci }, 9162306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C2", 9262306a36Sopenharmony_ci .irq_data = { 9362306a36Sopenharmony_ci .type = X86_ACPI_IRQ_TYPE_GPIOINT, 9462306a36Sopenharmony_ci .chip = "INT33FF:01", 9562306a36Sopenharmony_ci .index = 56, 9662306a36Sopenharmony_ci .trigger = ACPI_EDGE_SENSITIVE, 9762306a36Sopenharmony_ci .polarity = ACPI_ACTIVE_LOW, 9862306a36Sopenharmony_ci }, 9962306a36Sopenharmony_ci }, { 10062306a36Sopenharmony_ci /* Wacom Digitizer in keyboard half */ 10162306a36Sopenharmony_ci .board_info = { 10262306a36Sopenharmony_ci .type = "hid-over-i2c", 10362306a36Sopenharmony_ci .addr = 0x09, 10462306a36Sopenharmony_ci .dev_name = "wacom", 10562306a36Sopenharmony_ci .swnode = &lenovo_yb1_x90_wacom_node, 10662306a36Sopenharmony_ci }, 10762306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C4", 10862306a36Sopenharmony_ci .irq_data = { 10962306a36Sopenharmony_ci .type = X86_ACPI_IRQ_TYPE_GPIOINT, 11062306a36Sopenharmony_ci .chip = "INT33FF:01", 11162306a36Sopenharmony_ci .index = 49, 11262306a36Sopenharmony_ci .trigger = ACPI_LEVEL_SENSITIVE, 11362306a36Sopenharmony_ci .polarity = ACPI_ACTIVE_LOW, 11462306a36Sopenharmony_ci }, 11562306a36Sopenharmony_ci }, { 11662306a36Sopenharmony_ci /* LP8557 Backlight controller */ 11762306a36Sopenharmony_ci .board_info = { 11862306a36Sopenharmony_ci .type = "lp8557", 11962306a36Sopenharmony_ci .addr = 0x2c, 12062306a36Sopenharmony_ci .dev_name = "lp8557", 12162306a36Sopenharmony_ci .platform_data = &lenovo_lp8557_pdata, 12262306a36Sopenharmony_ci }, 12362306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C4", 12462306a36Sopenharmony_ci }, { 12562306a36Sopenharmony_ci /* HiDeep IST940E Touchscreen in display half */ 12662306a36Sopenharmony_ci .board_info = { 12762306a36Sopenharmony_ci .type = "hideep_ts", 12862306a36Sopenharmony_ci .addr = 0x6c, 12962306a36Sopenharmony_ci .dev_name = "hideep_ts", 13062306a36Sopenharmony_ci .swnode = &lenovo_yb1_x90_hideep_ts_node, 13162306a36Sopenharmony_ci }, 13262306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C6", 13362306a36Sopenharmony_ci .irq_data = { 13462306a36Sopenharmony_ci .type = X86_ACPI_IRQ_TYPE_GPIOINT, 13562306a36Sopenharmony_ci .chip = "INT33FF:03", 13662306a36Sopenharmony_ci .index = 77, 13762306a36Sopenharmony_ci .trigger = ACPI_LEVEL_SENSITIVE, 13862306a36Sopenharmony_ci .polarity = ACPI_ACTIVE_LOW, 13962306a36Sopenharmony_ci }, 14062306a36Sopenharmony_ci }, 14162306a36Sopenharmony_ci}; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = { 14462306a36Sopenharmony_ci { 14562306a36Sopenharmony_ci .name = "yogabook-touch-kbd-digitizer-switch", 14662306a36Sopenharmony_ci .id = PLATFORM_DEVID_NONE, 14762306a36Sopenharmony_ci }, 14862306a36Sopenharmony_ci}; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci/* 15162306a36Sopenharmony_ci * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of 15262306a36Sopenharmony_ci * the number '0' add the link manually. 15362306a36Sopenharmony_ci */ 15462306a36Sopenharmony_cistatic const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = { 15562306a36Sopenharmony_ci { 15662306a36Sopenharmony_ci .ctrl_hid = "8086228A", 15762306a36Sopenharmony_ci .ctrl_uid = "1", 15862306a36Sopenharmony_ci .ctrl_devname = "serial0", 15962306a36Sopenharmony_ci .serdev_hid = "BCM2E1A", 16062306a36Sopenharmony_ci }, 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = { 16462306a36Sopenharmony_ci .button = { 16562306a36Sopenharmony_ci .code = SW_LID, 16662306a36Sopenharmony_ci .active_low = true, 16762306a36Sopenharmony_ci .desc = "lid_sw", 16862306a36Sopenharmony_ci .type = EV_SW, 16962306a36Sopenharmony_ci .wakeup = true, 17062306a36Sopenharmony_ci .debounce_interval = 50, 17162306a36Sopenharmony_ci }, 17262306a36Sopenharmony_ci .chip = "INT33FF:02", 17362306a36Sopenharmony_ci .pin = 19, 17462306a36Sopenharmony_ci}; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = { 17762306a36Sopenharmony_ci .dev_id = "i2c-goodix_ts", 17862306a36Sopenharmony_ci .table = { 17962306a36Sopenharmony_ci GPIO_LOOKUP("INT33FF:01", 53, "reset", GPIO_ACTIVE_HIGH), 18062306a36Sopenharmony_ci GPIO_LOOKUP("INT33FF:01", 56, "irq", GPIO_ACTIVE_HIGH), 18162306a36Sopenharmony_ci { } 18262306a36Sopenharmony_ci }, 18362306a36Sopenharmony_ci}; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic struct gpiod_lookup_table lenovo_yb1_x90_hideep_gpios = { 18662306a36Sopenharmony_ci .dev_id = "i2c-hideep_ts", 18762306a36Sopenharmony_ci .table = { 18862306a36Sopenharmony_ci GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW), 18962306a36Sopenharmony_ci { } 19062306a36Sopenharmony_ci }, 19162306a36Sopenharmony_ci}; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic struct gpiod_lookup_table lenovo_yb1_x90_wacom_gpios = { 19462306a36Sopenharmony_ci .dev_id = "i2c-wacom", 19562306a36Sopenharmony_ci .table = { 19662306a36Sopenharmony_ci GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_LOW), 19762306a36Sopenharmony_ci { } 19862306a36Sopenharmony_ci }, 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic struct gpiod_lookup_table * const lenovo_yb1_x90_gpios[] = { 20262306a36Sopenharmony_ci &lenovo_yb1_x90_hideep_gpios, 20362306a36Sopenharmony_ci &lenovo_yb1_x90_goodix_gpios, 20462306a36Sopenharmony_ci &lenovo_yb1_x90_wacom_gpios, 20562306a36Sopenharmony_ci NULL 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic int __init lenovo_yb1_x90_init(void) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci /* Enable the regulators used by the touchscreens */ 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* Vprog3B 3.0V used by the goodix touchscreen in the keyboard half */ 21362306a36Sopenharmony_ci intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* Vprog4D 3.0V used by the HiDeep touchscreen in the display half */ 21662306a36Sopenharmony_ci intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9f, 0x02, 0xff); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci /* Vprog5A 1.8V used by the HiDeep touchscreen in the display half */ 21962306a36Sopenharmony_ci intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Vprog5B 1.8V used by the goodix touchscreen in the keyboard half */ 22262306a36Sopenharmony_ci intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa1, 0x02, 0xff); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci return 0; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ciconst struct x86_dev_info lenovo_yogabook_x90_info __initconst = { 22862306a36Sopenharmony_ci .i2c_client_info = lenovo_yb1_x90_i2c_clients, 22962306a36Sopenharmony_ci .i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients), 23062306a36Sopenharmony_ci .pdev_info = lenovo_yb1_x90_pdevs, 23162306a36Sopenharmony_ci .pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs), 23262306a36Sopenharmony_ci .serdev_info = lenovo_yb1_x90_serdevs, 23362306a36Sopenharmony_ci .serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs), 23462306a36Sopenharmony_ci .gpio_button = &lenovo_yb1_x90_lid, 23562306a36Sopenharmony_ci .gpio_button_count = 1, 23662306a36Sopenharmony_ci .gpiod_lookup_tables = lenovo_yb1_x90_gpios, 23762306a36Sopenharmony_ci .init = lenovo_yb1_x90_init, 23862306a36Sopenharmony_ci}; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci/* Lenovo Yoga Book X91F/L Windows tablet needs manual instantiation of the fg client */ 24162306a36Sopenharmony_cistatic const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __initconst = { 24262306a36Sopenharmony_ci { 24362306a36Sopenharmony_ci /* BQ27542 fuel-gauge */ 24462306a36Sopenharmony_ci .board_info = { 24562306a36Sopenharmony_ci .type = "bq27542", 24662306a36Sopenharmony_ci .addr = 0x55, 24762306a36Sopenharmony_ci .dev_name = "bq27542", 24862306a36Sopenharmony_ci .swnode = &fg_bq25890_supply_node, 24962306a36Sopenharmony_ci }, 25062306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C1", 25162306a36Sopenharmony_ci }, 25262306a36Sopenharmony_ci}; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ciconst struct x86_dev_info lenovo_yogabook_x91_info __initconst = { 25562306a36Sopenharmony_ci .i2c_client_info = lenovo_yogabook_x91_i2c_clients, 25662306a36Sopenharmony_ci .i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients), 25762306a36Sopenharmony_ci}; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci/* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */ 26062306a36Sopenharmony_cistatic const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = { 26162306a36Sopenharmony_ci PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", tusb1211_chg_det_psy, 1), 26262306a36Sopenharmony_ci PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node), 26362306a36Sopenharmony_ci PROPERTY_ENTRY_BOOL("omit-battery-class"), 26462306a36Sopenharmony_ci PROPERTY_ENTRY_BOOL("disable-reset"), 26562306a36Sopenharmony_ci { } 26662306a36Sopenharmony_ci}; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = { 26962306a36Sopenharmony_ci .properties = lenovo_yoga_tab2_830_1050_bq24190_props, 27062306a36Sopenharmony_ci}; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = { 27362306a36Sopenharmony_ci .button = { 27462306a36Sopenharmony_ci .code = SW_LID, 27562306a36Sopenharmony_ci .active_low = true, 27662306a36Sopenharmony_ci .desc = "lid_sw", 27762306a36Sopenharmony_ci .type = EV_SW, 27862306a36Sopenharmony_ci .wakeup = true, 27962306a36Sopenharmony_ci .debounce_interval = 50, 28062306a36Sopenharmony_ci }, 28162306a36Sopenharmony_ci .chip = "INT33FC:02", 28262306a36Sopenharmony_ci .pin = 26, 28362306a36Sopenharmony_ci}; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/* This gets filled by lenovo_yoga_tab2_830_1050_init() */ 28662306a36Sopenharmony_cistatic struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { }; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initdata = { 28962306a36Sopenharmony_ci { 29062306a36Sopenharmony_ci /* 29162306a36Sopenharmony_ci * This must be the first entry because lenovo_yoga_tab2_830_1050_init() 29262306a36Sopenharmony_ci * may update its swnode. LSM303DA accelerometer + magnetometer. 29362306a36Sopenharmony_ci */ 29462306a36Sopenharmony_ci .board_info = { 29562306a36Sopenharmony_ci .type = "lsm303d", 29662306a36Sopenharmony_ci .addr = 0x1d, 29762306a36Sopenharmony_ci .dev_name = "lsm303d", 29862306a36Sopenharmony_ci }, 29962306a36Sopenharmony_ci .adapter_path = "\\_SB_.I2C5", 30062306a36Sopenharmony_ci }, { 30162306a36Sopenharmony_ci /* AL3320A ambient light sensor */ 30262306a36Sopenharmony_ci .board_info = { 30362306a36Sopenharmony_ci .type = "al3320a", 30462306a36Sopenharmony_ci .addr = 0x1c, 30562306a36Sopenharmony_ci .dev_name = "al3320a", 30662306a36Sopenharmony_ci }, 30762306a36Sopenharmony_ci .adapter_path = "\\_SB_.I2C5", 30862306a36Sopenharmony_ci }, { 30962306a36Sopenharmony_ci /* bq24292i battery charger */ 31062306a36Sopenharmony_ci .board_info = { 31162306a36Sopenharmony_ci .type = "bq24190", 31262306a36Sopenharmony_ci .addr = 0x6b, 31362306a36Sopenharmony_ci .dev_name = "bq24292i", 31462306a36Sopenharmony_ci .swnode = &lenovo_yoga_tab2_830_1050_bq24190_node, 31562306a36Sopenharmony_ci .platform_data = &bq24190_pdata, 31662306a36Sopenharmony_ci }, 31762306a36Sopenharmony_ci .adapter_path = "\\_SB_.I2C1", 31862306a36Sopenharmony_ci .irq_data = { 31962306a36Sopenharmony_ci .type = X86_ACPI_IRQ_TYPE_GPIOINT, 32062306a36Sopenharmony_ci .chip = "INT33FC:02", 32162306a36Sopenharmony_ci .index = 2, 32262306a36Sopenharmony_ci .trigger = ACPI_EDGE_SENSITIVE, 32362306a36Sopenharmony_ci .polarity = ACPI_ACTIVE_HIGH, 32462306a36Sopenharmony_ci }, 32562306a36Sopenharmony_ci }, { 32662306a36Sopenharmony_ci /* BQ27541 fuel-gauge */ 32762306a36Sopenharmony_ci .board_info = { 32862306a36Sopenharmony_ci .type = "bq27541", 32962306a36Sopenharmony_ci .addr = 0x55, 33062306a36Sopenharmony_ci .dev_name = "bq27541", 33162306a36Sopenharmony_ci .swnode = &fg_bq24190_supply_node, 33262306a36Sopenharmony_ci }, 33362306a36Sopenharmony_ci .adapter_path = "\\_SB_.I2C1", 33462306a36Sopenharmony_ci }, { 33562306a36Sopenharmony_ci /* Synaptics RMI touchscreen */ 33662306a36Sopenharmony_ci .board_info = { 33762306a36Sopenharmony_ci .type = "rmi4_i2c", 33862306a36Sopenharmony_ci .addr = 0x38, 33962306a36Sopenharmony_ci .dev_name = "rmi4_i2c", 34062306a36Sopenharmony_ci .platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata, 34162306a36Sopenharmony_ci }, 34262306a36Sopenharmony_ci .adapter_path = "\\_SB_.I2C6", 34362306a36Sopenharmony_ci .irq_data = { 34462306a36Sopenharmony_ci .type = X86_ACPI_IRQ_TYPE_APIC, 34562306a36Sopenharmony_ci .index = 0x45, 34662306a36Sopenharmony_ci .trigger = ACPI_EDGE_SENSITIVE, 34762306a36Sopenharmony_ci .polarity = ACPI_ACTIVE_HIGH, 34862306a36Sopenharmony_ci }, 34962306a36Sopenharmony_ci }, { 35062306a36Sopenharmony_ci /* LP8557 Backlight controller */ 35162306a36Sopenharmony_ci .board_info = { 35262306a36Sopenharmony_ci .type = "lp8557", 35362306a36Sopenharmony_ci .addr = 0x2c, 35462306a36Sopenharmony_ci .dev_name = "lp8557", 35562306a36Sopenharmony_ci .platform_data = &lenovo_lp8557_pdata, 35662306a36Sopenharmony_ci }, 35762306a36Sopenharmony_ci .adapter_path = "\\_SB_.I2C3", 35862306a36Sopenharmony_ci }, 35962306a36Sopenharmony_ci}; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = { 36262306a36Sopenharmony_ci .dev_id = "intel-int3496", 36362306a36Sopenharmony_ci .table = { 36462306a36Sopenharmony_ci GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW), 36562306a36Sopenharmony_ci GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH), 36662306a36Sopenharmony_ci { } 36762306a36Sopenharmony_ci }, 36862306a36Sopenharmony_ci}; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci#define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00" 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistatic struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = { 37362306a36Sopenharmony_ci .dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, 37462306a36Sopenharmony_ci .table = { 37562306a36Sopenharmony_ci GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH), 37662306a36Sopenharmony_ci GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH), 37762306a36Sopenharmony_ci GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH), 37862306a36Sopenharmony_ci GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW), 37962306a36Sopenharmony_ci { } 38062306a36Sopenharmony_ci }, 38162306a36Sopenharmony_ci}; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = { 38462306a36Sopenharmony_ci &lenovo_yoga_tab2_830_1050_int3496_gpios, 38562306a36Sopenharmony_ci &lenovo_yoga_tab2_830_1050_codec_gpios, 38662306a36Sopenharmony_ci NULL 38762306a36Sopenharmony_ci}; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic int __init lenovo_yoga_tab2_830_1050_init(void); 39062306a36Sopenharmony_cistatic void lenovo_yoga_tab2_830_1050_exit(void); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ciconst struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = { 39362306a36Sopenharmony_ci .i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients, 39462306a36Sopenharmony_ci .i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients), 39562306a36Sopenharmony_ci .pdev_info = int3496_pdevs, 39662306a36Sopenharmony_ci .pdev_count = 1, 39762306a36Sopenharmony_ci .gpio_button = &lenovo_yoga_tab2_830_1050_lid, 39862306a36Sopenharmony_ci .gpio_button_count = 1, 39962306a36Sopenharmony_ci .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios, 40062306a36Sopenharmony_ci .bat_swnode = &generic_lipo_hv_4v35_battery_node, 40162306a36Sopenharmony_ci .modules = bq24190_modules, 40262306a36Sopenharmony_ci .init = lenovo_yoga_tab2_830_1050_init, 40362306a36Sopenharmony_ci .exit = lenovo_yoga_tab2_830_1050_exit, 40462306a36Sopenharmony_ci}; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci/* 40762306a36Sopenharmony_ci * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same 40862306a36Sopenharmony_ci * mainboard, but the 830 uses a portrait LCD panel with a landscape touchscreen, 40962306a36Sopenharmony_ci * requiring the touchscreen driver to adjust the touch-coords to match the LCD. 41062306a36Sopenharmony_ci * And requiring the accelerometer to have a mount-matrix set to correct for 41162306a36Sopenharmony_ci * the 90° rotation of the LCD vs the frame. 41262306a36Sopenharmony_ci */ 41362306a36Sopenharmony_cistatic const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = { 41462306a36Sopenharmony_ci "0", "1", "0", 41562306a36Sopenharmony_ci "-1", "0", "0", 41662306a36Sopenharmony_ci "0", "0", "1" 41762306a36Sopenharmony_ci}; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic const struct property_entry lenovo_yoga_tab2_830_lms303d_props[] = { 42062306a36Sopenharmony_ci PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", lenovo_yoga_tab2_830_lms303d_mount_matrix), 42162306a36Sopenharmony_ci { } 42262306a36Sopenharmony_ci}; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_cistatic const struct software_node lenovo_yoga_tab2_830_lms303d_node = { 42562306a36Sopenharmony_ci .properties = lenovo_yoga_tab2_830_lms303d_props, 42662306a36Sopenharmony_ci}; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci struct gpio_desc *gpiod; 43162306a36Sopenharmony_ci int ret; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */ 43462306a36Sopenharmony_ci ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod); 43562306a36Sopenharmony_ci if (ret) 43662306a36Sopenharmony_ci return ret; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci ret = gpiod_get_value_cansleep(gpiod); 43962306a36Sopenharmony_ci if (ret) { 44062306a36Sopenharmony_ci pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n"); 44162306a36Sopenharmony_ci } else { 44262306a36Sopenharmony_ci pr_info("detected Lenovo Yoga Tablet 2 830F/L\n"); 44362306a36Sopenharmony_ci lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true; 44462306a36Sopenharmony_ci lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true; 44562306a36Sopenharmony_ci lenovo_yoga_tab2_830_1050_i2c_clients[0].board_info.swnode = 44662306a36Sopenharmony_ci &lenovo_yoga_tab2_830_lms303d_node; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci return 0; 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci/* SUS (INT33FC:02) pin 6 needs to be configured as pmu_clk for the audio codec */ 45362306a36Sopenharmony_cistatic const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map = 45462306a36Sopenharmony_ci PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk", 45562306a36Sopenharmony_ci "INT33FC:02", "pmu_clk2_grp", "pmu_clk"); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl; 45862306a36Sopenharmony_cistatic struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic int __init lenovo_yoga_tab2_830_1050_init_codec(void) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci struct device *codec_dev; 46362306a36Sopenharmony_ci struct pinctrl *pinctrl; 46462306a36Sopenharmony_ci int ret; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, 46762306a36Sopenharmony_ci LENOVO_YOGA_TAB2_830_1050_CODEC_NAME); 46862306a36Sopenharmony_ci if (!codec_dev) { 46962306a36Sopenharmony_ci pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME); 47062306a36Sopenharmony_ci return -ENODEV; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1); 47462306a36Sopenharmony_ci if (ret) 47562306a36Sopenharmony_ci goto err_put_device; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk"); 47862306a36Sopenharmony_ci if (IS_ERR(pinctrl)) { 47962306a36Sopenharmony_ci ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n"); 48062306a36Sopenharmony_ci goto err_unregister_mappings; 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci /* We're done with the codec_dev now */ 48462306a36Sopenharmony_ci put_device(codec_dev); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl; 48762306a36Sopenharmony_ci return 0; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cierr_unregister_mappings: 49062306a36Sopenharmony_ci pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map); 49162306a36Sopenharmony_cierr_put_device: 49262306a36Sopenharmony_ci put_device(codec_dev); 49362306a36Sopenharmony_ci return ret; 49462306a36Sopenharmony_ci} 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci/* 49762306a36Sopenharmony_ci * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off 49862306a36Sopenharmony_ci * gets used as pm_power_off handler. This causes "poweroff" on these tablets 49962306a36Sopenharmony_ci * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice* 50062306a36Sopenharmony_ci * followed by a normal 3 second press to recover. Avoid this by doing an EFI 50162306a36Sopenharmony_ci * poweroff instead. 50262306a36Sopenharmony_ci */ 50362306a36Sopenharmony_cistatic int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci return NOTIFY_DONE; 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cistatic int __init lenovo_yoga_tab2_830_1050_init(void) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci int ret; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci ret = lenovo_yoga_tab2_830_1050_init_touchscreen(); 51562306a36Sopenharmony_ci if (ret) 51662306a36Sopenharmony_ci return ret; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci ret = lenovo_yoga_tab2_830_1050_init_codec(); 51962306a36Sopenharmony_ci if (ret) 52062306a36Sopenharmony_ci return ret; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */ 52362306a36Sopenharmony_ci lenovo_yoga_tab2_830_1050_sys_off_handler = 52462306a36Sopenharmony_ci register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1, 52562306a36Sopenharmony_ci lenovo_yoga_tab2_830_1050_power_off, NULL); 52662306a36Sopenharmony_ci if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler)) 52762306a36Sopenharmony_ci return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci return 0; 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic void lenovo_yoga_tab2_830_1050_exit(void) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci if (lenovo_yoga_tab2_830_1050_codec_pinctrl) { 53762306a36Sopenharmony_ci pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl); 53862306a36Sopenharmony_ci pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map); 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci/* Lenovo Yoga Tab 3 Pro YT3-X90F */ 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci/* 54562306a36Sopenharmony_ci * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers, 54662306a36Sopenharmony_ci * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c. 54762306a36Sopenharmony_ci */ 54862306a36Sopenharmony_cistatic const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" }; 54962306a36Sopenharmony_cistatic const char * const bq25890_1_psy[] = { "bq25890-charger-1" }; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cistatic const struct property_entry fg_bq25890_1_supply_props[] = { 55262306a36Sopenharmony_ci PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy), 55362306a36Sopenharmony_ci { } 55462306a36Sopenharmony_ci}; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_cistatic const struct software_node fg_bq25890_1_supply_node = { 55762306a36Sopenharmony_ci .properties = fg_bq25890_1_supply_props, 55862306a36Sopenharmony_ci}; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci/* bq25892 charger settings for the flat lipo battery behind the screen */ 56162306a36Sopenharmony_cistatic const struct property_entry lenovo_yt3_bq25892_0_props[] = { 56262306a36Sopenharmony_ci PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers), 56362306a36Sopenharmony_ci PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"), 56462306a36Sopenharmony_ci PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40), 56562306a36Sopenharmony_ci PROPERTY_ENTRY_BOOL("linux,skip-reset"), 56662306a36Sopenharmony_ci /* Values taken from Android Factory Image */ 56762306a36Sopenharmony_ci PROPERTY_ENTRY_U32("ti,charge-current", 2048000), 56862306a36Sopenharmony_ci PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000), 56962306a36Sopenharmony_ci PROPERTY_ENTRY_U32("ti,termination-current", 128000), 57062306a36Sopenharmony_ci PROPERTY_ENTRY_U32("ti,precharge-current", 128000), 57162306a36Sopenharmony_ci PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000), 57262306a36Sopenharmony_ci PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000), 57362306a36Sopenharmony_ci PROPERTY_ENTRY_U32("ti,boost-max-current", 500000), 57462306a36Sopenharmony_ci PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"), 57562306a36Sopenharmony_ci { } 57662306a36Sopenharmony_ci}; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic const struct software_node lenovo_yt3_bq25892_0_node = { 57962306a36Sopenharmony_ci .properties = lenovo_yt3_bq25892_0_props, 58062306a36Sopenharmony_ci}; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic const struct property_entry lenovo_yt3_hideep_ts_props[] = { 58362306a36Sopenharmony_ci PROPERTY_ENTRY_U32("touchscreen-size-x", 1600), 58462306a36Sopenharmony_ci PROPERTY_ENTRY_U32("touchscreen-size-y", 2560), 58562306a36Sopenharmony_ci PROPERTY_ENTRY_U32("touchscreen-max-pressure", 255), 58662306a36Sopenharmony_ci { } 58762306a36Sopenharmony_ci}; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_cistatic const struct software_node lenovo_yt3_hideep_ts_node = { 59062306a36Sopenharmony_ci .properties = lenovo_yt3_hideep_ts_props, 59162306a36Sopenharmony_ci}; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { 59462306a36Sopenharmony_ci { 59562306a36Sopenharmony_ci /* bq27500 fuel-gauge for the flat lipo battery behind the screen */ 59662306a36Sopenharmony_ci .board_info = { 59762306a36Sopenharmony_ci .type = "bq27500", 59862306a36Sopenharmony_ci .addr = 0x55, 59962306a36Sopenharmony_ci .dev_name = "bq27500_0", 60062306a36Sopenharmony_ci .swnode = &fg_bq25890_supply_node, 60162306a36Sopenharmony_ci }, 60262306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C1", 60362306a36Sopenharmony_ci }, { 60462306a36Sopenharmony_ci /* bq25892 charger for the flat lipo battery behind the screen */ 60562306a36Sopenharmony_ci .board_info = { 60662306a36Sopenharmony_ci .type = "bq25892", 60762306a36Sopenharmony_ci .addr = 0x6b, 60862306a36Sopenharmony_ci .dev_name = "bq25892_0", 60962306a36Sopenharmony_ci .swnode = &lenovo_yt3_bq25892_0_node, 61062306a36Sopenharmony_ci }, 61162306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C1", 61262306a36Sopenharmony_ci .irq_data = { 61362306a36Sopenharmony_ci .type = X86_ACPI_IRQ_TYPE_GPIOINT, 61462306a36Sopenharmony_ci .chip = "INT33FF:01", 61562306a36Sopenharmony_ci .index = 5, 61662306a36Sopenharmony_ci .trigger = ACPI_EDGE_SENSITIVE, 61762306a36Sopenharmony_ci .polarity = ACPI_ACTIVE_LOW, 61862306a36Sopenharmony_ci }, 61962306a36Sopenharmony_ci }, { 62062306a36Sopenharmony_ci /* bq27500 fuel-gauge for the round li-ion cells in the hinge */ 62162306a36Sopenharmony_ci .board_info = { 62262306a36Sopenharmony_ci .type = "bq27500", 62362306a36Sopenharmony_ci .addr = 0x55, 62462306a36Sopenharmony_ci .dev_name = "bq27500_1", 62562306a36Sopenharmony_ci .swnode = &fg_bq25890_1_supply_node, 62662306a36Sopenharmony_ci }, 62762306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C2", 62862306a36Sopenharmony_ci }, { 62962306a36Sopenharmony_ci /* HiDeep IST520E Touchscreen */ 63062306a36Sopenharmony_ci .board_info = { 63162306a36Sopenharmony_ci .type = "hideep_ts", 63262306a36Sopenharmony_ci .addr = 0x6c, 63362306a36Sopenharmony_ci .dev_name = "hideep_ts", 63462306a36Sopenharmony_ci .swnode = &lenovo_yt3_hideep_ts_node, 63562306a36Sopenharmony_ci }, 63662306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C6", 63762306a36Sopenharmony_ci .irq_data = { 63862306a36Sopenharmony_ci .type = X86_ACPI_IRQ_TYPE_GPIOINT, 63962306a36Sopenharmony_ci .chip = "INT33FF:03", 64062306a36Sopenharmony_ci .index = 77, 64162306a36Sopenharmony_ci .trigger = ACPI_LEVEL_SENSITIVE, 64262306a36Sopenharmony_ci .polarity = ACPI_ACTIVE_LOW, 64362306a36Sopenharmony_ci }, 64462306a36Sopenharmony_ci }, { 64562306a36Sopenharmony_ci /* LP8557 Backlight controller */ 64662306a36Sopenharmony_ci .board_info = { 64762306a36Sopenharmony_ci .type = "lp8557", 64862306a36Sopenharmony_ci .addr = 0x2c, 64962306a36Sopenharmony_ci .dev_name = "lp8557", 65062306a36Sopenharmony_ci .platform_data = &lenovo_lp8557_pdata, 65162306a36Sopenharmony_ci }, 65262306a36Sopenharmony_ci .adapter_path = "\\_SB_.PCI0.I2C1", 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci}; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic int __init lenovo_yt3_init(void) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci struct gpio_desc *gpiod; 65962306a36Sopenharmony_ci int ret; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci /* 66262306a36Sopenharmony_ci * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins 66362306a36Sopenharmony_ci * connected to GPIOs, rather then having them hardwired to the correct 66462306a36Sopenharmony_ci * values as is normally done. 66562306a36Sopenharmony_ci * 66662306a36Sopenharmony_ci * The bq25890_charger driver controls these through I2C, but this only 66762306a36Sopenharmony_ci * works if not overridden by the pins. Set these pins here: 66862306a36Sopenharmony_ci * 1. Set /CE to 0 to allow charging. 66962306a36Sopenharmony_ci * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of 67062306a36Sopenharmony_ci * the main "bq25892_1" charger is used when necessary. 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci /* /CE pin */ 67462306a36Sopenharmony_ci ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod); 67562306a36Sopenharmony_ci if (ret < 0) 67662306a36Sopenharmony_ci return ret; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci /* 67962306a36Sopenharmony_ci * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw" 68062306a36Sopenharmony_ci * gpio_desc, that is there is no way to pass lookup-flags like 68162306a36Sopenharmony_ci * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since 68262306a36Sopenharmony_ci * the /CE pin is active-low, but not marked as such in the gpio_desc. 68362306a36Sopenharmony_ci */ 68462306a36Sopenharmony_ci gpiod_set_value(gpiod, 0); 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci /* OTG pin */ 68762306a36Sopenharmony_ci ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod); 68862306a36Sopenharmony_ci if (ret < 0) 68962306a36Sopenharmony_ci return ret; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci gpiod_set_value(gpiod, 0); 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci /* Enable the regulators used by the touchscreen */ 69462306a36Sopenharmony_ci intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff); 69562306a36Sopenharmony_ci intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci return 0; 69862306a36Sopenharmony_ci} 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_cistatic struct gpiod_lookup_table lenovo_yt3_hideep_gpios = { 70162306a36Sopenharmony_ci .dev_id = "i2c-hideep_ts", 70262306a36Sopenharmony_ci .table = { 70362306a36Sopenharmony_ci GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW), 70462306a36Sopenharmony_ci { } 70562306a36Sopenharmony_ci }, 70662306a36Sopenharmony_ci}; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_cistatic struct gpiod_lookup_table * const lenovo_yt3_gpios[] = { 70962306a36Sopenharmony_ci &lenovo_yt3_hideep_gpios, 71062306a36Sopenharmony_ci NULL 71162306a36Sopenharmony_ci}; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ciconst struct x86_dev_info lenovo_yt3_info __initconst = { 71462306a36Sopenharmony_ci .i2c_client_info = lenovo_yt3_i2c_clients, 71562306a36Sopenharmony_ci .i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients), 71662306a36Sopenharmony_ci .gpiod_lookup_tables = lenovo_yt3_gpios, 71762306a36Sopenharmony_ci .init = lenovo_yt3_init, 71862306a36Sopenharmony_ci}; 719