]> Git Repo - linux.git/blob - drivers/platform/x86/x86-android-tablets/core.c
i2c: Fix conditional for substituting empty ACPI functions
[linux.git] / drivers / platform / x86 / x86-android-tablets / core.c
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 <[email protected]>
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/consumer.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 #include "../serdev_helpers.h"
25
26 static struct platform_device *x86_android_tablet_device;
27
28 /*
29  * This helper allows getting a gpio_desc *before* the actual device consuming
30  * the GPIO has been instantiated. This function _must_ only be used to handle
31  * this special case such as e.g. :
32  *
33  * 1. Getting an IRQ from a GPIO for i2c_board_info.irq which is passed to
34  * i2c_client_new() to instantiate i2c_client-s; or
35  * 2. Calling desc_to_gpio() to get an old style GPIO number for gpio_keys
36  * platform_data which still uses old style GPIO numbers.
37  *
38  * Since the consuming device has not been instatiated yet a dynamic lookup
39  * is generated using the special x86_android_tablet dev for dev_id.
40  *
41  * For normal GPIO lookups a standard static gpiod_lookup_table _must_ be used.
42  */
43 int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id,
44                                  bool active_low, enum gpiod_flags dflags,
45                                  struct gpio_desc **desc)
46 {
47         struct gpiod_lookup_table *lookup;
48         struct gpio_desc *gpiod;
49
50         lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL);
51         if (!lookup)
52                 return -ENOMEM;
53
54         lookup->dev_id = KBUILD_MODNAME;
55         lookup->table[0] =
56                 GPIO_LOOKUP(chip, pin, con_id, active_low ? GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH);
57
58         gpiod_add_lookup_table(lookup);
59         gpiod = devm_gpiod_get(&x86_android_tablet_device->dev, con_id, dflags);
60         gpiod_remove_lookup_table(lookup);
61         kfree(lookup);
62
63         if (IS_ERR(gpiod)) {
64                 pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), chip, pin);
65                 return PTR_ERR(gpiod);
66         }
67
68         if (desc)
69                 *desc = gpiod;
70
71         return 0;
72 }
73
74 int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
75 {
76         struct irq_fwspec fwspec = { };
77         struct irq_domain *domain;
78         struct acpi_device *adev;
79         struct gpio_desc *gpiod;
80         unsigned int irq_type;
81         acpi_handle handle;
82         acpi_status status;
83         int irq, ret;
84
85         switch (data->type) {
86         case X86_ACPI_IRQ_TYPE_APIC:
87                 /*
88                  * The DSDT may already reference the GSI in a device skipped by
89                  * acpi_quirk_skip_i2c_client_enumeration(). Unregister the GSI
90                  * to avoid EBUSY errors in this case.
91                  */
92                 acpi_unregister_gsi(data->index);
93                 irq = acpi_register_gsi(NULL, data->index, data->trigger, data->polarity);
94                 if (irq < 0)
95                         pr_err("error %d getting APIC IRQ %d\n", irq, data->index);
96
97                 return irq;
98         case X86_ACPI_IRQ_TYPE_GPIOINT:
99                 /* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */
100                 ret = x86_android_tablet_get_gpiod(data->chip, data->index, data->con_id,
101                                                    false, GPIOD_ASIS, &gpiod);
102                 if (ret)
103                         return ret;
104
105                 irq = gpiod_to_irq(gpiod);
106                 if (irq < 0) {
107                         pr_err("error %d getting IRQ %s %d\n", irq, data->chip, data->index);
108                         return irq;
109                 }
110
111                 irq_type = acpi_dev_get_irq_type(data->trigger, data->polarity);
112                 if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq))
113                         irq_set_irq_type(irq, irq_type);
114
115                 if (data->free_gpio)
116                         devm_gpiod_put(&x86_android_tablet_device->dev, gpiod);
117
118                 return irq;
119         case X86_ACPI_IRQ_TYPE_PMIC:
120                 status = acpi_get_handle(NULL, data->chip, &handle);
121                 if (ACPI_FAILURE(status)) {
122                         pr_err("error could not get %s handle\n", data->chip);
123                         return -ENODEV;
124                 }
125
126                 adev = acpi_fetch_acpi_dev(handle);
127                 if (!adev) {
128                         pr_err("error could not get %s adev\n", data->chip);
129                         return -ENODEV;
130                 }
131
132                 fwspec.fwnode = acpi_fwnode_handle(adev);
133                 domain = irq_find_matching_fwspec(&fwspec, data->domain);
134                 if (!domain) {
135                         pr_err("error could not find IRQ domain for %s\n", data->chip);
136                         return -ENODEV;
137                 }
138
139                 return irq_create_mapping(domain, data->index);
140         default:
141                 return 0;
142         }
143 }
144
145 static int i2c_client_count;
146 static int spi_dev_count;
147 static int pdev_count;
148 static int serdev_count;
149 static struct i2c_client **i2c_clients;
150 static struct spi_device **spi_devs;
151 static struct platform_device **pdevs;
152 static struct serdev_device **serdevs;
153 static struct gpio_keys_button *buttons;
154 static struct gpiod_lookup_table * const *gpiod_lookup_tables;
155 static const struct software_node *bat_swnode;
156 static void (*exit_handler)(void);
157
158 static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info,
159                                              int idx)
160 {
161         const struct x86_i2c_client_info *client_info = &dev_info->i2c_client_info[idx];
162         struct i2c_board_info board_info = client_info->board_info;
163         struct i2c_adapter *adap;
164         acpi_handle handle;
165         acpi_status status;
166
167         board_info.irq = x86_acpi_irq_helper_get(&client_info->irq_data);
168         if (board_info.irq < 0)
169                 return board_info.irq;
170
171         status = acpi_get_handle(NULL, client_info->adapter_path, &handle);
172         if (ACPI_FAILURE(status)) {
173                 pr_err("Error could not get %s handle\n", client_info->adapter_path);
174                 return -ENODEV;
175         }
176
177         adap = i2c_acpi_find_adapter_by_handle(handle);
178         if (!adap) {
179                 pr_err("error could not get %s adapter\n", client_info->adapter_path);
180                 return -ENODEV;
181         }
182
183         i2c_clients[idx] = i2c_new_client_device(adap, &board_info);
184         put_device(&adap->dev);
185         if (IS_ERR(i2c_clients[idx]))
186                 return dev_err_probe(&adap->dev, PTR_ERR(i2c_clients[idx]),
187                                       "creating I2C-client %d\n", idx);
188
189         return 0;
190 }
191
192 static __init int x86_instantiate_spi_dev(const struct x86_dev_info *dev_info, int idx)
193 {
194         const struct x86_spi_dev_info *spi_dev_info = &dev_info->spi_dev_info[idx];
195         struct spi_board_info board_info = spi_dev_info->board_info;
196         struct spi_controller *controller;
197         struct acpi_device *adev;
198         acpi_handle handle;
199         acpi_status status;
200
201         board_info.irq = x86_acpi_irq_helper_get(&spi_dev_info->irq_data);
202         if (board_info.irq < 0)
203                 return board_info.irq;
204
205         status = acpi_get_handle(NULL, spi_dev_info->ctrl_path, &handle);
206         if (ACPI_FAILURE(status)) {
207                 pr_err("Error could not get %s handle\n", spi_dev_info->ctrl_path);
208                 return -ENODEV;
209         }
210
211         adev = acpi_fetch_acpi_dev(handle);
212         if (!adev) {
213                 pr_err("Error could not get adev for %s\n", spi_dev_info->ctrl_path);
214                 return -ENODEV;
215         }
216
217         controller = acpi_spi_find_controller_by_adev(adev);
218         if (!controller) {
219                 pr_err("Error could not get SPI controller for %s\n", spi_dev_info->ctrl_path);
220                 return -ENODEV;
221         }
222
223         spi_devs[idx] = spi_new_device(controller, &board_info);
224         put_device(&controller->dev);
225         if (!spi_devs[idx])
226                 return dev_err_probe(&controller->dev, -ENOMEM,
227                                      "creating SPI-device %d\n", idx);
228
229         return 0;
230 }
231
232 static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx)
233 {
234         struct acpi_device *serdev_adev;
235         struct serdev_device *serdev;
236         struct device *ctrl_dev;
237         int ret = -ENODEV;
238
239         ctrl_dev = get_serdev_controller(info->ctrl_hid, info->ctrl_uid, 0,
240                                          info->ctrl_devname);
241         if (IS_ERR(ctrl_dev))
242                 return PTR_ERR(ctrl_dev);
243
244         serdev_adev = acpi_dev_get_first_match_dev(info->serdev_hid, NULL, -1);
245         if (!serdev_adev) {
246                 pr_err("error could not get %s serdev adev\n", info->serdev_hid);
247                 goto put_ctrl_dev;
248         }
249
250         serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev));
251         if (!serdev) {
252                 ret = -ENOMEM;
253                 goto put_serdev_adev;
254         }
255
256         ACPI_COMPANION_SET(&serdev->dev, serdev_adev);
257         acpi_device_set_enumerated(serdev_adev);
258
259         ret = serdev_device_add(serdev);
260         if (ret) {
261                 dev_err(&serdev->dev, "error %d adding serdev\n", ret);
262                 serdev_device_put(serdev);
263                 goto put_serdev_adev;
264         }
265
266         serdevs[idx] = serdev;
267
268 put_serdev_adev:
269         acpi_dev_put(serdev_adev);
270 put_ctrl_dev:
271         put_device(ctrl_dev);
272         return ret;
273 }
274
275 static void x86_android_tablet_remove(struct platform_device *pdev)
276 {
277         int i;
278
279         for (i = serdev_count - 1; i >= 0; i--) {
280                 if (serdevs[i])
281                         serdev_device_remove(serdevs[i]);
282         }
283
284         kfree(serdevs);
285
286         for (i = pdev_count - 1; i >= 0; i--)
287                 platform_device_unregister(pdevs[i]);
288
289         kfree(pdevs);
290         kfree(buttons);
291
292         for (i = spi_dev_count - 1; i >= 0; i--)
293                 spi_unregister_device(spi_devs[i]);
294
295         kfree(spi_devs);
296
297         for (i = i2c_client_count - 1; i >= 0; i--)
298                 i2c_unregister_device(i2c_clients[i]);
299
300         kfree(i2c_clients);
301
302         if (exit_handler)
303                 exit_handler();
304
305         for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
306                 gpiod_remove_lookup_table(gpiod_lookup_tables[i]);
307
308         software_node_unregister(bat_swnode);
309 }
310
311 static __init int x86_android_tablet_probe(struct platform_device *pdev)
312 {
313         const struct x86_dev_info *dev_info;
314         const struct dmi_system_id *id;
315         int i, ret = 0;
316
317         id = dmi_first_match(x86_android_tablet_ids);
318         if (!id)
319                 return -ENODEV;
320
321         dev_info = id->driver_data;
322         /* Allow x86_android_tablet_device use before probe() exits */
323         x86_android_tablet_device = pdev;
324
325         /*
326          * Since this runs from module_init() it cannot use -EPROBE_DEFER,
327          * instead pre-load any modules which are listed as requirements.
328          */
329         for (i = 0; dev_info->modules && dev_info->modules[i]; i++)
330                 request_module(dev_info->modules[i]);
331
332         bat_swnode = dev_info->bat_swnode;
333         if (bat_swnode) {
334                 ret = software_node_register(bat_swnode);
335                 if (ret)
336                         return ret;
337         }
338
339         gpiod_lookup_tables = dev_info->gpiod_lookup_tables;
340         for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
341                 gpiod_add_lookup_table(gpiod_lookup_tables[i]);
342
343         if (dev_info->init) {
344                 ret = dev_info->init(&pdev->dev);
345                 if (ret < 0) {
346                         x86_android_tablet_remove(pdev);
347                         return ret;
348                 }
349                 exit_handler = dev_info->exit;
350         }
351
352         i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL);
353         if (!i2c_clients) {
354                 x86_android_tablet_remove(pdev);
355                 return -ENOMEM;
356         }
357
358         i2c_client_count = dev_info->i2c_client_count;
359         for (i = 0; i < i2c_client_count; i++) {
360                 ret = x86_instantiate_i2c_client(dev_info, i);
361                 if (ret < 0) {
362                         x86_android_tablet_remove(pdev);
363                         return ret;
364                 }
365         }
366
367         spi_devs = kcalloc(dev_info->spi_dev_count, sizeof(*spi_devs), GFP_KERNEL);
368         if (!spi_devs) {
369                 x86_android_tablet_remove(pdev);
370                 return -ENOMEM;
371         }
372
373         spi_dev_count = dev_info->spi_dev_count;
374         for (i = 0; i < spi_dev_count; i++) {
375                 ret = x86_instantiate_spi_dev(dev_info, i);
376                 if (ret < 0) {
377                         x86_android_tablet_remove(pdev);
378                         return ret;
379                 }
380         }
381
382         /* + 1 to make space for (optional) gpio_keys_button pdev */
383         pdevs = kcalloc(dev_info->pdev_count + 1, sizeof(*pdevs), GFP_KERNEL);
384         if (!pdevs) {
385                 x86_android_tablet_remove(pdev);
386                 return -ENOMEM;
387         }
388
389         pdev_count = dev_info->pdev_count;
390         for (i = 0; i < pdev_count; i++) {
391                 pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]);
392                 if (IS_ERR(pdevs[i])) {
393                         x86_android_tablet_remove(pdev);
394                         return PTR_ERR(pdevs[i]);
395                 }
396         }
397
398         serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL);
399         if (!serdevs) {
400                 x86_android_tablet_remove(pdev);
401                 return -ENOMEM;
402         }
403
404         serdev_count = dev_info->serdev_count;
405         for (i = 0; i < serdev_count; i++) {
406                 ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i);
407                 if (ret < 0) {
408                         x86_android_tablet_remove(pdev);
409                         return ret;
410                 }
411         }
412
413         if (dev_info->gpio_button_count) {
414                 struct gpio_keys_platform_data pdata = { };
415                 struct gpio_desc *gpiod;
416
417                 buttons = kcalloc(dev_info->gpio_button_count, sizeof(*buttons), GFP_KERNEL);
418                 if (!buttons) {
419                         x86_android_tablet_remove(pdev);
420                         return -ENOMEM;
421                 }
422
423                 for (i = 0; i < dev_info->gpio_button_count; i++) {
424                         ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip,
425                                                            dev_info->gpio_button[i].pin,
426                                                            dev_info->gpio_button[i].button.desc,
427                                                            false, GPIOD_IN, &gpiod);
428                         if (ret < 0) {
429                                 x86_android_tablet_remove(pdev);
430                                 return ret;
431                         }
432
433                         buttons[i] = dev_info->gpio_button[i].button;
434                         buttons[i].gpio = desc_to_gpio(gpiod);
435                         /* Release gpiod so that gpio-keys can request it */
436                         devm_gpiod_put(&x86_android_tablet_device->dev, gpiod);
437                 }
438
439                 pdata.buttons = buttons;
440                 pdata.nbuttons = dev_info->gpio_button_count;
441
442                 pdevs[pdev_count] = platform_device_register_data(&pdev->dev, "gpio-keys",
443                                                                   PLATFORM_DEVID_AUTO,
444                                                                   &pdata, sizeof(pdata));
445                 if (IS_ERR(pdevs[pdev_count])) {
446                         x86_android_tablet_remove(pdev);
447                         return PTR_ERR(pdevs[pdev_count]);
448                 }
449                 pdev_count++;
450         }
451
452         return 0;
453 }
454
455 static struct platform_driver x86_android_tablet_driver = {
456         .driver = {
457                 .name = KBUILD_MODNAME,
458         },
459         .remove_new = x86_android_tablet_remove,
460 };
461
462 static int __init x86_android_tablet_init(void)
463 {
464         x86_android_tablet_device = platform_create_bundle(&x86_android_tablet_driver,
465                                                    x86_android_tablet_probe,
466                                                    NULL, 0, NULL, 0);
467
468         return PTR_ERR_OR_ZERO(x86_android_tablet_device);
469 }
470 module_init(x86_android_tablet_init);
471
472 static void __exit x86_android_tablet_exit(void)
473 {
474         platform_device_unregister(x86_android_tablet_device);
475         platform_driver_unregister(&x86_android_tablet_driver);
476 }
477 module_exit(x86_android_tablet_exit);
478
479 MODULE_AUTHOR("Hans de Goede <[email protected]>");
480 MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver");
481 MODULE_LICENSE("GPL");
This page took 0.06724 seconds and 4 git commands to generate.