xref: /linux/drivers/platform/x86/x86-android-tablets/lenovo.c (revision 34dc1baba215b826e454b8d19e4f24adbeb7d00d)
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