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
lenovo_yb1_x90_init(void)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
lenovo_yoga_tab2_830_1050_init_touchscreen(void)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
lenovo_yoga_tab2_830_1050_init_codec(void)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 */
lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data * data)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
lenovo_yoga_tab2_830_1050_init(void)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
lenovo_yoga_tab2_830_1050_exit(void)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
lenovo_yt3_init(void)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