1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Board info for Lenovo X86 tablets which ship with Android as the factory image 4 * and which have broken DSDT tables. 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-2023 Hans de Goede <hdegoede@redhat.com> 9 */ 10 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13 #include <linux/efi.h> 14 #include <linux/gpio/machine.h> 15 #include <linux/mfd/intel_soc_pmic.h> 16 #include <linux/pinctrl/consumer.h> 17 #include <linux/pinctrl/machine.h> 18 #include <linux/platform_data/lp855x.h> 19 #include <linux/platform_device.h> 20 #include <linux/reboot.h> 21 #include <linux/rmi.h> 22 #include <linux/spi/spi.h> 23 24 #include "shared-psy-info.h" 25 #include "x86-android-tablets.h" 26 27 /* 28 * Various Lenovo models use a TI LP8557 LED backlight controller with its PWM 29 * input connected to a PWM output coming from the LCD panel's controller. 30 * The Android kernels have a hack in the i915 driver to write a non-standard 31 * panel specific DSI register to set the duty-cycle of the LCD's PWM output. 32 * 33 * To avoid having to have a similar hack in the mainline kernel program the 34 * LP8557 to directly set the level and use the lp855x_bl driver for control. 35 */ 36 static struct lp855x_platform_data lenovo_lp8557_pdata = { 37 .device_control = 0x86, 38 .initial_brightness = 128, 39 }; 40 41 /* Lenovo Yoga Book X90F / X90L's Android factory img has everything hardcoded */ 42 43 static const struct property_entry lenovo_yb1_x90_wacom_props[] = { 44 PROPERTY_ENTRY_U32("hid-descr-addr", 0x0001), 45 PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 150), 46 { } 47 }; 48 49 static const struct software_node lenovo_yb1_x90_wacom_node = { 50 .properties = lenovo_yb1_x90_wacom_props, 51 }; 52 53 /* 54 * The HiDeep IST940E touchscreen comes up in I2C-HID mode. The native protocol 55 * reports ABS_MT_PRESSURE and ABS_MT_TOUCH_MAJOR which are not reported in HID 56 * mode, so using native mode is preferred. 57 * It could alternatively be used in HID mode by changing the properties to: 58 * PROPERTY_ENTRY_U32("hid-descr-addr", 0x0020), 59 * PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120), 60 * and changing board_info.type to "hid-over-i2c". 61 */ 62 static const struct property_entry lenovo_yb1_x90_hideep_ts_props[] = { 63 PROPERTY_ENTRY_U32("touchscreen-size-x", 1200), 64 PROPERTY_ENTRY_U32("touchscreen-size-y", 1920), 65 PROPERTY_ENTRY_U32("touchscreen-max-pressure", 16384), 66 PROPERTY_ENTRY_BOOL("hideep,force-native-protocol"), 67 { } 68 }; 69 70 static const struct software_node lenovo_yb1_x90_hideep_ts_node = { 71 .properties = lenovo_yb1_x90_hideep_ts_props, 72 }; 73 74 static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst = { 75 { 76 /* BQ27542 fuel-gauge */ 77 .board_info = { 78 .type = "bq27542", 79 .addr = 0x55, 80 .dev_name = "bq27542", 81 .swnode = &fg_bq25890_supply_node, 82 }, 83 .adapter_path = "\\_SB_.PCI0.I2C1", 84 }, { 85 /* Goodix Touchscreen in keyboard half */ 86 .board_info = { 87 .type = "GDIX1001:00", 88 .addr = 0x14, 89 .dev_name = "goodix_ts", 90 }, 91 .adapter_path = "\\_SB_.PCI0.I2C2", 92 .irq_data = { 93 .type = X86_ACPI_IRQ_TYPE_GPIOINT, 94 .chip = "INT33FF:01", 95 .index = 56, 96 .trigger = ACPI_EDGE_SENSITIVE, 97 .polarity = ACPI_ACTIVE_LOW, 98 }, 99 }, { 100 /* Wacom Digitizer in keyboard half */ 101 .board_info = { 102 .type = "hid-over-i2c", 103 .addr = 0x09, 104 .dev_name = "wacom", 105 .swnode = &lenovo_yb1_x90_wacom_node, 106 }, 107 .adapter_path = "\\_SB_.PCI0.I2C4", 108 .irq_data = { 109 .type = X86_ACPI_IRQ_TYPE_GPIOINT, 110 .chip = "INT33FF:01", 111 .index = 49, 112 .trigger = ACPI_LEVEL_SENSITIVE, 113 .polarity = ACPI_ACTIVE_LOW, 114 }, 115 }, { 116 /* LP8557 Backlight controller */ 117 .board_info = { 118 .type = "lp8557", 119 .addr = 0x2c, 120 .dev_name = "lp8557", 121 .platform_data = &lenovo_lp8557_pdata, 122 }, 123 .adapter_path = "\\_SB_.PCI0.I2C4", 124 }, { 125 /* HiDeep IST940E Touchscreen in display half */ 126 .board_info = { 127 .type = "hideep_ts", 128 .addr = 0x6c, 129 .dev_name = "hideep_ts", 130 .swnode = &lenovo_yb1_x90_hideep_ts_node, 131 }, 132 .adapter_path = "\\_SB_.PCI0.I2C6", 133 .irq_data = { 134 .type = X86_ACPI_IRQ_TYPE_GPIOINT, 135 .chip = "INT33FF:03", 136 .index = 77, 137 .trigger = ACPI_LEVEL_SENSITIVE, 138 .polarity = ACPI_ACTIVE_LOW, 139 }, 140 }, 141 }; 142 143 static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = { 144 { 145 .name = "yogabook-touch-kbd-digitizer-switch", 146 .id = PLATFORM_DEVID_NONE, 147 }, 148 }; 149 150 /* 151 * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of 152 * the number '0' add the link manually. 153 */ 154 static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = { 155 { 156 .ctrl_hid = "8086228A", 157 .ctrl_uid = "1", 158 .ctrl_devname = "serial0", 159 .serdev_hid = "BCM2E1A", 160 }, 161 }; 162 163 static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = { 164 .button = { 165 .code = SW_LID, 166 .active_low = true, 167 .desc = "lid_sw", 168 .type = EV_SW, 169 .wakeup = true, 170 .debounce_interval = 50, 171 }, 172 .chip = "INT33FF:02", 173 .pin = 19, 174 }; 175 176 static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = { 177 .dev_id = "i2c-goodix_ts", 178 .table = { 179 GPIO_LOOKUP("INT33FF:01", 53, "reset", GPIO_ACTIVE_HIGH), 180 GPIO_LOOKUP("INT33FF:01", 56, "irq", GPIO_ACTIVE_HIGH), 181 { } 182 }, 183 }; 184 185 static struct gpiod_lookup_table lenovo_yb1_x90_hideep_gpios = { 186 .dev_id = "i2c-hideep_ts", 187 .table = { 188 GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW), 189 { } 190 }, 191 }; 192 193 static struct gpiod_lookup_table lenovo_yb1_x90_wacom_gpios = { 194 .dev_id = "i2c-wacom", 195 .table = { 196 GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_LOW), 197 { } 198 }, 199 }; 200 201 static struct gpiod_lookup_table * const lenovo_yb1_x90_gpios[] = { 202 &lenovo_yb1_x90_hideep_gpios, 203 &lenovo_yb1_x90_goodix_gpios, 204 &lenovo_yb1_x90_wacom_gpios, 205 NULL 206 }; 207 208 static int __init lenovo_yb1_x90_init(void) 209 { 210 /* Enable the regulators used by the touchscreens */ 211 212 /* Vprog3B 3.0V used by the goodix touchscreen in the keyboard half */ 213 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff); 214 215 /* Vprog4D 3.0V used by the HiDeep touchscreen in the display half */ 216 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9f, 0x02, 0xff); 217 218 /* Vprog5A 1.8V used by the HiDeep touchscreen in the display half */ 219 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff); 220 221 /* Vprog5B 1.8V used by the goodix touchscreen in the keyboard half */ 222 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa1, 0x02, 0xff); 223 224 return 0; 225 } 226 227 const struct x86_dev_info lenovo_yogabook_x90_info __initconst = { 228 .i2c_client_info = lenovo_yb1_x90_i2c_clients, 229 .i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients), 230 .pdev_info = lenovo_yb1_x90_pdevs, 231 .pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs), 232 .serdev_info = lenovo_yb1_x90_serdevs, 233 .serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs), 234 .gpio_button = &lenovo_yb1_x90_lid, 235 .gpio_button_count = 1, 236 .gpiod_lookup_tables = lenovo_yb1_x90_gpios, 237 .init = lenovo_yb1_x90_init, 238 }; 239 240 /* Lenovo Yoga Book X91F/L Windows tablet needs manual instantiation of the fg client */ 241 static const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __initconst = { 242 { 243 /* BQ27542 fuel-gauge */ 244 .board_info = { 245 .type = "bq27542", 246 .addr = 0x55, 247 .dev_name = "bq27542", 248 .swnode = &fg_bq25890_supply_node, 249 }, 250 .adapter_path = "\\_SB_.PCI0.I2C1", 251 }, 252 }; 253 254 const struct x86_dev_info lenovo_yogabook_x91_info __initconst = { 255 .i2c_client_info = lenovo_yogabook_x91_i2c_clients, 256 .i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients), 257 }; 258 259 /* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */ 260 static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = { 261 PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", tusb1211_chg_det_psy, 1), 262 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node), 263 PROPERTY_ENTRY_BOOL("omit-battery-class"), 264 PROPERTY_ENTRY_BOOL("disable-reset"), 265 { } 266 }; 267 268 static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = { 269 .properties = lenovo_yoga_tab2_830_1050_bq24190_props, 270 }; 271 272 static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = { 273 .button = { 274 .code = SW_LID, 275 .active_low = true, 276 .desc = "lid_sw", 277 .type = EV_SW, 278 .wakeup = true, 279 .debounce_interval = 50, 280 }, 281 .chip = "INT33FC:02", 282 .pin = 26, 283 }; 284 285 /* This gets filled by lenovo_yoga_tab2_830_1050_init() */ 286 static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { }; 287 288 static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initdata = { 289 { 290 /* 291 * This must be the first entry because lenovo_yoga_tab2_830_1050_init() 292 * may update its swnode. LSM303DA accelerometer + magnetometer. 293 */ 294 .board_info = { 295 .type = "lsm303d", 296 .addr = 0x1d, 297 .dev_name = "lsm303d", 298 }, 299 .adapter_path = "\\_SB_.I2C5", 300 }, { 301 /* AL3320A ambient light sensor */ 302 .board_info = { 303 .type = "al3320a", 304 .addr = 0x1c, 305 .dev_name = "al3320a", 306 }, 307 .adapter_path = "\\_SB_.I2C5", 308 }, { 309 /* bq24292i battery charger */ 310 .board_info = { 311 .type = "bq24190", 312 .addr = 0x6b, 313 .dev_name = "bq24292i", 314 .swnode = &lenovo_yoga_tab2_830_1050_bq24190_node, 315 .platform_data = &bq24190_pdata, 316 }, 317 .adapter_path = "\\_SB_.I2C1", 318 .irq_data = { 319 .type = X86_ACPI_IRQ_TYPE_GPIOINT, 320 .chip = "INT33FC:02", 321 .index = 2, 322 .trigger = ACPI_EDGE_SENSITIVE, 323 .polarity = ACPI_ACTIVE_HIGH, 324 }, 325 }, { 326 /* BQ27541 fuel-gauge */ 327 .board_info = { 328 .type = "bq27541", 329 .addr = 0x55, 330 .dev_name = "bq27541", 331 .swnode = &fg_bq24190_supply_node, 332 }, 333 .adapter_path = "\\_SB_.I2C1", 334 }, { 335 /* Synaptics RMI touchscreen */ 336 .board_info = { 337 .type = "rmi4_i2c", 338 .addr = 0x38, 339 .dev_name = "rmi4_i2c", 340 .platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata, 341 }, 342 .adapter_path = "\\_SB_.I2C6", 343 .irq_data = { 344 .type = X86_ACPI_IRQ_TYPE_APIC, 345 .index = 0x45, 346 .trigger = ACPI_EDGE_SENSITIVE, 347 .polarity = ACPI_ACTIVE_HIGH, 348 }, 349 }, { 350 /* LP8557 Backlight controller */ 351 .board_info = { 352 .type = "lp8557", 353 .addr = 0x2c, 354 .dev_name = "lp8557", 355 .platform_data = &lenovo_lp8557_pdata, 356 }, 357 .adapter_path = "\\_SB_.I2C3", 358 }, 359 }; 360 361 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = { 362 .dev_id = "intel-int3496", 363 .table = { 364 GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW), 365 GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH), 366 { } 367 }, 368 }; 369 370 #define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00" 371 372 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = { 373 .dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, 374 .table = { 375 GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH), 376 GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH), 377 GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH), 378 GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW), 379 { } 380 }, 381 }; 382 383 static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = { 384 &lenovo_yoga_tab2_830_1050_int3496_gpios, 385 &lenovo_yoga_tab2_830_1050_codec_gpios, 386 NULL 387 }; 388 389 static int __init lenovo_yoga_tab2_830_1050_init(void); 390 static void lenovo_yoga_tab2_830_1050_exit(void); 391 392 const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = { 393 .i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients, 394 .i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients), 395 .pdev_info = int3496_pdevs, 396 .pdev_count = 1, 397 .gpio_button = &lenovo_yoga_tab2_830_1050_lid, 398 .gpio_button_count = 1, 399 .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios, 400 .bat_swnode = &generic_lipo_hv_4v35_battery_node, 401 .modules = bq24190_modules, 402 .init = lenovo_yoga_tab2_830_1050_init, 403 .exit = lenovo_yoga_tab2_830_1050_exit, 404 }; 405 406 /* 407 * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same 408 * mainboard, but the 830 uses a portrait LCD panel with a landscape touchscreen, 409 * requiring the touchscreen driver to adjust the touch-coords to match the LCD. 410 * And requiring the accelerometer to have a mount-matrix set to correct for 411 * the 90° rotation of the LCD vs the frame. 412 */ 413 static const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = { 414 "0", "1", "0", 415 "-1", "0", "0", 416 "0", "0", "1" 417 }; 418 419 static const struct property_entry lenovo_yoga_tab2_830_lms303d_props[] = { 420 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", lenovo_yoga_tab2_830_lms303d_mount_matrix), 421 { } 422 }; 423 424 static const struct software_node lenovo_yoga_tab2_830_lms303d_node = { 425 .properties = lenovo_yoga_tab2_830_lms303d_props, 426 }; 427 428 static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void) 429 { 430 struct gpio_desc *gpiod; 431 int ret; 432 433 /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */ 434 ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod); 435 if (ret) 436 return ret; 437 438 ret = gpiod_get_value_cansleep(gpiod); 439 if (ret) { 440 pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n"); 441 } else { 442 pr_info("detected Lenovo Yoga Tablet 2 830F/L\n"); 443 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true; 444 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true; 445 lenovo_yoga_tab2_830_1050_i2c_clients[0].board_info.swnode = 446 &lenovo_yoga_tab2_830_lms303d_node; 447 } 448 449 return 0; 450 } 451 452 /* SUS (INT33FC:02) pin 6 needs to be configured as pmu_clk for the audio codec */ 453 static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map = 454 PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk", 455 "INT33FC:02", "pmu_clk2_grp", "pmu_clk"); 456 457 static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl; 458 static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler; 459 460 static int __init lenovo_yoga_tab2_830_1050_init_codec(void) 461 { 462 struct device *codec_dev; 463 struct pinctrl *pinctrl; 464 int ret; 465 466 codec_dev = bus_find_device_by_name(&spi_bus_type, NULL, 467 LENOVO_YOGA_TAB2_830_1050_CODEC_NAME); 468 if (!codec_dev) { 469 pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME); 470 return -ENODEV; 471 } 472 473 ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1); 474 if (ret) 475 goto err_put_device; 476 477 pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk"); 478 if (IS_ERR(pinctrl)) { 479 ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n"); 480 goto err_unregister_mappings; 481 } 482 483 /* We're done with the codec_dev now */ 484 put_device(codec_dev); 485 486 lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl; 487 return 0; 488 489 err_unregister_mappings: 490 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map); 491 err_put_device: 492 put_device(codec_dev); 493 return ret; 494 } 495 496 /* 497 * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off 498 * gets used as pm_power_off handler. This causes "poweroff" on these tablets 499 * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice* 500 * followed by a normal 3 second press to recover. Avoid this by doing an EFI 501 * poweroff instead. 502 */ 503 static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data) 504 { 505 efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); 506 507 return NOTIFY_DONE; 508 } 509 510 static int __init lenovo_yoga_tab2_830_1050_init(void) 511 { 512 int ret; 513 514 ret = lenovo_yoga_tab2_830_1050_init_touchscreen(); 515 if (ret) 516 return ret; 517 518 ret = lenovo_yoga_tab2_830_1050_init_codec(); 519 if (ret) 520 return ret; 521 522 /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */ 523 lenovo_yoga_tab2_830_1050_sys_off_handler = 524 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1, 525 lenovo_yoga_tab2_830_1050_power_off, NULL); 526 if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler)) 527 return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler); 528 529 return 0; 530 } 531 532 static void lenovo_yoga_tab2_830_1050_exit(void) 533 { 534 unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler); 535 536 if (lenovo_yoga_tab2_830_1050_codec_pinctrl) { 537 pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl); 538 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map); 539 } 540 } 541 542 /* Lenovo Yoga Tab 3 Pro YT3-X90F */ 543 544 /* 545 * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers, 546 * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c. 547 */ 548 static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" }; 549 static const char * const bq25890_1_psy[] = { "bq25890-charger-1" }; 550 551 static const struct property_entry fg_bq25890_1_supply_props[] = { 552 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy), 553 { } 554 }; 555 556 static const struct software_node fg_bq25890_1_supply_node = { 557 .properties = fg_bq25890_1_supply_props, 558 }; 559 560 /* bq25892 charger settings for the flat lipo battery behind the screen */ 561 static const struct property_entry lenovo_yt3_bq25892_0_props[] = { 562 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers), 563 PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"), 564 PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40), 565 PROPERTY_ENTRY_BOOL("linux,skip-reset"), 566 /* Values taken from Android Factory Image */ 567 PROPERTY_ENTRY_U32("ti,charge-current", 2048000), 568 PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000), 569 PROPERTY_ENTRY_U32("ti,termination-current", 128000), 570 PROPERTY_ENTRY_U32("ti,precharge-current", 128000), 571 PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000), 572 PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000), 573 PROPERTY_ENTRY_U32("ti,boost-max-current", 500000), 574 PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"), 575 { } 576 }; 577 578 static const struct software_node lenovo_yt3_bq25892_0_node = { 579 .properties = lenovo_yt3_bq25892_0_props, 580 }; 581 582 static const struct property_entry lenovo_yt3_hideep_ts_props[] = { 583 PROPERTY_ENTRY_U32("touchscreen-size-x", 1600), 584 PROPERTY_ENTRY_U32("touchscreen-size-y", 2560), 585 PROPERTY_ENTRY_U32("touchscreen-max-pressure", 255), 586 { } 587 }; 588 589 static const struct software_node lenovo_yt3_hideep_ts_node = { 590 .properties = lenovo_yt3_hideep_ts_props, 591 }; 592 593 static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = { 594 { 595 /* bq27500 fuel-gauge for the flat lipo battery behind the screen */ 596 .board_info = { 597 .type = "bq27500", 598 .addr = 0x55, 599 .dev_name = "bq27500_0", 600 .swnode = &fg_bq25890_supply_node, 601 }, 602 .adapter_path = "\\_SB_.PCI0.I2C1", 603 }, { 604 /* bq25892 charger for the flat lipo battery behind the screen */ 605 .board_info = { 606 .type = "bq25892", 607 .addr = 0x6b, 608 .dev_name = "bq25892_0", 609 .swnode = &lenovo_yt3_bq25892_0_node, 610 }, 611 .adapter_path = "\\_SB_.PCI0.I2C1", 612 .irq_data = { 613 .type = X86_ACPI_IRQ_TYPE_GPIOINT, 614 .chip = "INT33FF:01", 615 .index = 5, 616 .trigger = ACPI_EDGE_SENSITIVE, 617 .polarity = ACPI_ACTIVE_LOW, 618 }, 619 }, { 620 /* bq27500 fuel-gauge for the round li-ion cells in the hinge */ 621 .board_info = { 622 .type = "bq27500", 623 .addr = 0x55, 624 .dev_name = "bq27500_1", 625 .swnode = &fg_bq25890_1_supply_node, 626 }, 627 .adapter_path = "\\_SB_.PCI0.I2C2", 628 }, { 629 /* HiDeep IST520E Touchscreen */ 630 .board_info = { 631 .type = "hideep_ts", 632 .addr = 0x6c, 633 .dev_name = "hideep_ts", 634 .swnode = &lenovo_yt3_hideep_ts_node, 635 }, 636 .adapter_path = "\\_SB_.PCI0.I2C6", 637 .irq_data = { 638 .type = X86_ACPI_IRQ_TYPE_GPIOINT, 639 .chip = "INT33FF:03", 640 .index = 77, 641 .trigger = ACPI_LEVEL_SENSITIVE, 642 .polarity = ACPI_ACTIVE_LOW, 643 }, 644 }, { 645 /* LP8557 Backlight controller */ 646 .board_info = { 647 .type = "lp8557", 648 .addr = 0x2c, 649 .dev_name = "lp8557", 650 .platform_data = &lenovo_lp8557_pdata, 651 }, 652 .adapter_path = "\\_SB_.PCI0.I2C1", 653 } 654 }; 655 656 static int __init lenovo_yt3_init(void) 657 { 658 struct gpio_desc *gpiod; 659 int ret; 660 661 /* 662 * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins 663 * connected to GPIOs, rather then having them hardwired to the correct 664 * values as is normally done. 665 * 666 * The bq25890_charger driver controls these through I2C, but this only 667 * works if not overridden by the pins. Set these pins here: 668 * 1. Set /CE to 0 to allow charging. 669 * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of 670 * the main "bq25892_1" charger is used when necessary. 671 */ 672 673 /* /CE pin */ 674 ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod); 675 if (ret < 0) 676 return ret; 677 678 /* 679 * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw" 680 * gpio_desc, that is there is no way to pass lookup-flags like 681 * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since 682 * the /CE pin is active-low, but not marked as such in the gpio_desc. 683 */ 684 gpiod_set_value(gpiod, 0); 685 686 /* OTG pin */ 687 ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod); 688 if (ret < 0) 689 return ret; 690 691 gpiod_set_value(gpiod, 0); 692 693 /* Enable the regulators used by the touchscreen */ 694 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff); 695 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff); 696 697 return 0; 698 } 699 700 static struct gpiod_lookup_table lenovo_yt3_hideep_gpios = { 701 .dev_id = "i2c-hideep_ts", 702 .table = { 703 GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW), 704 { } 705 }, 706 }; 707 708 static struct gpiod_lookup_table * const lenovo_yt3_gpios[] = { 709 &lenovo_yt3_hideep_gpios, 710 NULL 711 }; 712 713 const struct x86_dev_info lenovo_yt3_info __initconst = { 714 .i2c_client_info = lenovo_yt3_i2c_clients, 715 .i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients), 716 .gpiod_lookup_tables = lenovo_yt3_gpios, 717 .init = lenovo_yt3_init, 718 }; 719