1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * DMI based code to deal with broken DSDTs on X86 tablets which ship with
4  * Android as (part of) the factory image. The factory kernels shipped on these
5  * devices typically have a bunch of things hardcoded, rather than specified
6  * in their DSDT.
7  *
8  * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com>
9  */
10 
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 
13 #include <linux/acpi.h>
14 #include <linux/dmi.h>
15 #include <linux/gpio/driver.h>
16 #include <linux/gpio/machine.h>
17 #include <linux/irq.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/serdev.h>
21 #include <linux/string.h>
22 
23 #include "x86-android-tablets.h"
24 /* For gpiochip_get_desc() which is EXPORT_SYMBOL_GPL() */
25 #include "../../../gpio/gpiolib.h"
26 #include "../../../gpio/gpiolib-acpi.h"
27 
28 static struct platform_device *x86_android_tablet_device;
29 
30 static int gpiochip_find_match_label(struct gpio_chip *gc, void *data)
31 {
32 	return gc->label && !strcmp(gc->label, data);
33 }
34 
35 int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc)
36 {
37 	struct gpio_desc *gpiod;
38 	struct gpio_chip *chip;
39 
40 	chip = gpiochip_find((void *)label, gpiochip_find_match_label);
41 	if (!chip) {
42 		pr_err("error cannot find GPIO chip %s\n", label);
43 		return -ENODEV;
44 	}
45 
46 	gpiod = gpiochip_get_desc(chip, pin);
47 	if (IS_ERR(gpiod)) {
48 		pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin);
49 		return PTR_ERR(gpiod);
50 	}
51 
52 	*desc = gpiod;
53 	return 0;
54 }
55 
56 int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
57 {
58 	struct irq_fwspec fwspec = { };
59 	struct irq_domain *domain;
60 	struct acpi_device *adev;
61 	struct gpio_desc *gpiod;
62 	unsigned int irq_type;
63 	acpi_handle handle;
64 	acpi_status status;
65 	int irq, ret;
66 
67 	switch (data->type) {
68 	case X86_ACPI_IRQ_TYPE_APIC:
69 		/*
70 		 * The DSDT may already reference the GSI in a device skipped by
71 		 * acpi_quirk_skip_i2c_client_enumeration(). Unregister the GSI
72 		 * to avoid EBUSY errors in this case.
73 		 */
74 		acpi_unregister_gsi(data->index);
75 		irq = acpi_register_gsi(NULL, data->index, data->trigger, data->polarity);
76 		if (irq < 0)
77 			pr_err("error %d getting APIC IRQ %d\n", irq, data->index);
78 
79 		return irq;
80 	case X86_ACPI_IRQ_TYPE_GPIOINT:
81 		/* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */
82 		ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod);
83 		if (ret)
84 			return ret;
85 
86 		irq = gpiod_to_irq(gpiod);
87 		if (irq < 0) {
88 			pr_err("error %d getting IRQ %s %d\n", irq, data->chip, data->index);
89 			return irq;
90 		}
91 
92 		irq_type = acpi_dev_get_irq_type(data->trigger, data->polarity);
93 		if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq))
94 			irq_set_irq_type(irq, irq_type);
95 
96 		return irq;
97 	case X86_ACPI_IRQ_TYPE_PMIC:
98 		status = acpi_get_handle(NULL, data->chip, &handle);
99 		if (ACPI_FAILURE(status)) {
100 			pr_err("error could not get %s handle\n", data->chip);
101 			return -ENODEV;
102 		}
103 
104 		adev = acpi_fetch_acpi_dev(handle);
105 		if (!adev) {
106 			pr_err("error could not get %s adev\n", data->chip);
107 			return -ENODEV;
108 		}
109 
110 		fwspec.fwnode = acpi_fwnode_handle(adev);
111 		domain = irq_find_matching_fwspec(&fwspec, data->domain);
112 		if (!domain) {
113 			pr_err("error could not find IRQ domain for %s\n", data->chip);
114 			return -ENODEV;
115 		}
116 
117 		return irq_create_mapping(domain, data->index);
118 	default:
119 		return 0;
120 	}
121 }
122 
123 static int i2c_client_count;
124 static int pdev_count;
125 static int serdev_count;
126 static struct i2c_client **i2c_clients;
127 static struct platform_device **pdevs;
128 static struct serdev_device **serdevs;
129 static struct gpio_keys_button *buttons;
130 static struct gpiod_lookup_table * const *gpiod_lookup_tables;
131 static const struct software_node *bat_swnode;
132 static void (*exit_handler)(void);
133 
134 static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info,
135 					     int idx)
136 {
137 	const struct x86_i2c_client_info *client_info = &dev_info->i2c_client_info[idx];
138 	struct i2c_board_info board_info = client_info->board_info;
139 	struct i2c_adapter *adap;
140 	acpi_handle handle;
141 	acpi_status status;
142 
143 	board_info.irq = x86_acpi_irq_helper_get(&client_info->irq_data);
144 	if (board_info.irq < 0)
145 		return board_info.irq;
146 
147 	status = acpi_get_handle(NULL, client_info->adapter_path, &handle);
148 	if (ACPI_FAILURE(status)) {
149 		pr_err("Error could not get %s handle\n", client_info->adapter_path);
150 		return -ENODEV;
151 	}
152 
153 	adap = i2c_acpi_find_adapter_by_handle(handle);
154 	if (!adap) {
155 		pr_err("error could not get %s adapter\n", client_info->adapter_path);
156 		return -ENODEV;
157 	}
158 
159 	i2c_clients[idx] = i2c_new_client_device(adap, &board_info);
160 	put_device(&adap->dev);
161 	if (IS_ERR(i2c_clients[idx]))
162 		return dev_err_probe(&adap->dev, PTR_ERR(i2c_clients[idx]),
163 				      "creating I2C-client %d\n", idx);
164 
165 	return 0;
166 }
167 
168 static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx)
169 {
170 	struct acpi_device *ctrl_adev, *serdev_adev;
171 	struct serdev_device *serdev;
172 	struct device *ctrl_dev;
173 	int ret = -ENODEV;
174 
175 	ctrl_adev = acpi_dev_get_first_match_dev(info->ctrl_hid, info->ctrl_uid, -1);
176 	if (!ctrl_adev) {
177 		pr_err("error could not get %s/%s ctrl adev\n",
178 		       info->ctrl_hid, info->ctrl_uid);
179 		return -ENODEV;
180 	}
181 
182 	serdev_adev = acpi_dev_get_first_match_dev(info->serdev_hid, NULL, -1);
183 	if (!serdev_adev) {
184 		pr_err("error could not get %s serdev adev\n", info->serdev_hid);
185 		goto put_ctrl_adev;
186 	}
187 
188 	/* get_first_physical_node() returns a weak ref, no need to put() it */
189 	ctrl_dev = acpi_get_first_physical_node(ctrl_adev);
190 	if (!ctrl_dev)	{
191 		pr_err("error could not get %s/%s ctrl physical dev\n",
192 		       info->ctrl_hid, info->ctrl_uid);
193 		goto put_serdev_adev;
194 	}
195 
196 	/* ctrl_dev now points to the controller's parent, get the controller */
197 	ctrl_dev = device_find_child_by_name(ctrl_dev, info->ctrl_devname);
198 	if (!ctrl_dev) {
199 		pr_err("error could not get %s/%s %s ctrl dev\n",
200 		       info->ctrl_hid, info->ctrl_uid, info->ctrl_devname);
201 		goto put_serdev_adev;
202 	}
203 
204 	serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev));
205 	if (!serdev) {
206 		ret = -ENOMEM;
207 		goto put_serdev_adev;
208 	}
209 
210 	ACPI_COMPANION_SET(&serdev->dev, serdev_adev);
211 	acpi_device_set_enumerated(serdev_adev);
212 
213 	ret = serdev_device_add(serdev);
214 	if (ret) {
215 		dev_err(&serdev->dev, "error %d adding serdev\n", ret);
216 		serdev_device_put(serdev);
217 		goto put_serdev_adev;
218 	}
219 
220 	serdevs[idx] = serdev;
221 
222 put_serdev_adev:
223 	acpi_dev_put(serdev_adev);
224 put_ctrl_adev:
225 	acpi_dev_put(ctrl_adev);
226 	return ret;
227 }
228 
229 static void x86_android_tablet_remove(struct platform_device *pdev)
230 {
231 	int i;
232 
233 	for (i = 0; i < serdev_count; i++) {
234 		if (serdevs[i])
235 			serdev_device_remove(serdevs[i]);
236 	}
237 
238 	kfree(serdevs);
239 
240 	for (i = 0; i < pdev_count; i++)
241 		platform_device_unregister(pdevs[i]);
242 
243 	kfree(pdevs);
244 	kfree(buttons);
245 
246 	for (i = 0; i < i2c_client_count; i++)
247 		i2c_unregister_device(i2c_clients[i]);
248 
249 	kfree(i2c_clients);
250 
251 	if (exit_handler)
252 		exit_handler();
253 
254 	for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
255 		gpiod_remove_lookup_table(gpiod_lookup_tables[i]);
256 
257 	software_node_unregister(bat_swnode);
258 }
259 
260 static __init int x86_android_tablet_probe(struct platform_device *pdev)
261 {
262 	const struct x86_dev_info *dev_info;
263 	const struct dmi_system_id *id;
264 	struct gpio_chip *chip;
265 	int i, ret = 0;
266 
267 	id = dmi_first_match(x86_android_tablet_ids);
268 	if (!id)
269 		return -ENODEV;
270 
271 	dev_info = id->driver_data;
272 	/* Allow x86_android_tablet_device use before probe() exits */
273 	x86_android_tablet_device = pdev;
274 
275 	/*
276 	 * The broken DSDTs on these devices often also include broken
277 	 * _AEI (ACPI Event Interrupt) handlers, disable these.
278 	 */
279 	if (dev_info->invalid_aei_gpiochip) {
280 		chip = gpiochip_find(dev_info->invalid_aei_gpiochip,
281 				     gpiochip_find_match_label);
282 		if (!chip) {
283 			pr_err("error cannot find GPIO chip %s\n", dev_info->invalid_aei_gpiochip);
284 			return -ENODEV;
285 		}
286 		acpi_gpiochip_free_interrupts(chip);
287 	}
288 
289 	/*
290 	 * Since this runs from module_init() it cannot use -EPROBE_DEFER,
291 	 * instead pre-load any modules which are listed as requirements.
292 	 */
293 	for (i = 0; dev_info->modules && dev_info->modules[i]; i++)
294 		request_module(dev_info->modules[i]);
295 
296 	bat_swnode = dev_info->bat_swnode;
297 	if (bat_swnode) {
298 		ret = software_node_register(bat_swnode);
299 		if (ret)
300 			return ret;
301 	}
302 
303 	gpiod_lookup_tables = dev_info->gpiod_lookup_tables;
304 	for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
305 		gpiod_add_lookup_table(gpiod_lookup_tables[i]);
306 
307 	if (dev_info->init) {
308 		ret = dev_info->init();
309 		if (ret < 0) {
310 			x86_android_tablet_remove(pdev);
311 			return ret;
312 		}
313 		exit_handler = dev_info->exit;
314 	}
315 
316 	i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL);
317 	if (!i2c_clients) {
318 		x86_android_tablet_remove(pdev);
319 		return -ENOMEM;
320 	}
321 
322 	i2c_client_count = dev_info->i2c_client_count;
323 	for (i = 0; i < i2c_client_count; i++) {
324 		ret = x86_instantiate_i2c_client(dev_info, i);
325 		if (ret < 0) {
326 			x86_android_tablet_remove(pdev);
327 			return ret;
328 		}
329 	}
330 
331 	/* + 1 to make space for (optional) gpio_keys_button pdev */
332 	pdevs = kcalloc(dev_info->pdev_count + 1, sizeof(*pdevs), GFP_KERNEL);
333 	if (!pdevs) {
334 		x86_android_tablet_remove(pdev);
335 		return -ENOMEM;
336 	}
337 
338 	pdev_count = dev_info->pdev_count;
339 	for (i = 0; i < pdev_count; i++) {
340 		pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]);
341 		if (IS_ERR(pdevs[i])) {
342 			ret = PTR_ERR(pdevs[i]);
343 			x86_android_tablet_remove(pdev);
344 			return ret;
345 		}
346 	}
347 
348 	serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL);
349 	if (!serdevs) {
350 		x86_android_tablet_remove(pdev);
351 		return -ENOMEM;
352 	}
353 
354 	serdev_count = dev_info->serdev_count;
355 	for (i = 0; i < serdev_count; i++) {
356 		ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i);
357 		if (ret < 0) {
358 			x86_android_tablet_remove(pdev);
359 			return ret;
360 		}
361 	}
362 
363 	if (dev_info->gpio_button_count) {
364 		struct gpio_keys_platform_data pdata = { };
365 		struct gpio_desc *gpiod;
366 
367 		buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL);
368 		if (!buttons) {
369 			x86_android_tablet_remove(pdev);
370 			return -ENOMEM;
371 		}
372 
373 		for (i = 0; i < dev_info->gpio_button_count; i++) {
374 			ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip,
375 							   dev_info->gpio_button[i].pin, &gpiod);
376 			if (ret < 0) {
377 				x86_android_tablet_remove(pdev);
378 				return ret;
379 			}
380 
381 			buttons[i] = dev_info->gpio_button[i].button;
382 			buttons[i].gpio = desc_to_gpio(gpiod);
383 		}
384 
385 		pdata.buttons = buttons;
386 		pdata.nbuttons = dev_info->gpio_button_count;
387 
388 		pdevs[pdev_count] = platform_device_register_data(NULL, "gpio-keys",
389 								  PLATFORM_DEVID_AUTO,
390 								  &pdata, sizeof(pdata));
391 		if (IS_ERR(pdevs[pdev_count])) {
392 			ret = PTR_ERR(pdevs[pdev_count]);
393 			x86_android_tablet_remove(pdev);
394 			return ret;
395 		}
396 		pdev_count++;
397 	}
398 
399 	return 0;
400 }
401 
402 static struct platform_driver x86_android_tablet_driver = {
403 	.driver = {
404 		.name = KBUILD_MODNAME,
405 	},
406 	.remove_new = x86_android_tablet_remove,
407 };
408 
409 static int __init x86_android_tablet_init(void)
410 {
411 	x86_android_tablet_device = platform_create_bundle(&x86_android_tablet_driver,
412 						   x86_android_tablet_probe,
413 						   NULL, 0, NULL, 0);
414 
415 	return PTR_ERR_OR_ZERO(x86_android_tablet_device);
416 }
417 module_init(x86_android_tablet_init);
418 
419 static void __exit x86_android_tablet_exit(void)
420 {
421 	platform_device_unregister(x86_android_tablet_device);
422 	platform_driver_unregister(&x86_android_tablet_driver);
423 }
424 module_exit(x86_android_tablet_exit);
425 
426 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
427 MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver");
428 MODULE_LICENSE("GPL");
429