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