0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0012
0013 #include <linux/acpi.h>
0014 #include <linux/dmi.h>
0015 #include <linux/efi.h>
0016 #include <linux/gpio_keys.h>
0017 #include <linux/gpio/consumer.h>
0018 #include <linux/gpio/driver.h>
0019 #include <linux/gpio/machine.h>
0020 #include <linux/i2c.h>
0021 #include <linux/input.h>
0022 #include <linux/irq.h>
0023 #include <linux/irqdomain.h>
0024 #include <linux/module.h>
0025 #include <linux/mod_devicetable.h>
0026 #include <linux/pinctrl/consumer.h>
0027 #include <linux/pinctrl/machine.h>
0028 #include <linux/platform_data/lp855x.h>
0029 #include <linux/platform_device.h>
0030 #include <linux/power/bq24190_charger.h>
0031 #include <linux/reboot.h>
0032 #include <linux/rmi.h>
0033 #include <linux/serdev.h>
0034 #include <linux/spi/spi.h>
0035 #include <linux/string.h>
0036
0037 #include "../../gpio/gpiolib.h"
0038 #include "../../gpio/gpiolib-acpi.h"
0039
0040
0041
0042
0043
0044 enum x86_acpi_irq_type {
0045 X86_ACPI_IRQ_TYPE_NONE,
0046 X86_ACPI_IRQ_TYPE_APIC,
0047 X86_ACPI_IRQ_TYPE_GPIOINT,
0048 X86_ACPI_IRQ_TYPE_PMIC,
0049 };
0050
0051 struct x86_acpi_irq_data {
0052 char *chip;
0053 enum x86_acpi_irq_type type;
0054 enum irq_domain_bus_token domain;
0055 int index;
0056 int trigger;
0057 int polarity;
0058 };
0059
0060 static int gpiochip_find_match_label(struct gpio_chip *gc, void *data)
0061 {
0062 return gc->label && !strcmp(gc->label, data);
0063 }
0064
0065 static int x86_android_tablet_get_gpiod(char *label, int pin, struct gpio_desc **desc)
0066 {
0067 struct gpio_desc *gpiod;
0068 struct gpio_chip *chip;
0069
0070 chip = gpiochip_find(label, gpiochip_find_match_label);
0071 if (!chip) {
0072 pr_err("error cannot find GPIO chip %s\n", label);
0073 return -ENODEV;
0074 }
0075
0076 gpiod = gpiochip_get_desc(chip, pin);
0077 if (IS_ERR(gpiod)) {
0078 pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin);
0079 return PTR_ERR(gpiod);
0080 }
0081
0082 *desc = gpiod;
0083 return 0;
0084 }
0085
0086 static int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
0087 {
0088 struct irq_fwspec fwspec = { };
0089 struct irq_domain *domain;
0090 struct acpi_device *adev;
0091 struct gpio_desc *gpiod;
0092 unsigned int irq_type;
0093 acpi_handle handle;
0094 acpi_status status;
0095 int irq, ret;
0096
0097 switch (data->type) {
0098 case X86_ACPI_IRQ_TYPE_APIC:
0099
0100
0101
0102
0103
0104 acpi_unregister_gsi(data->index);
0105 irq = acpi_register_gsi(NULL, data->index, data->trigger, data->polarity);
0106 if (irq < 0)
0107 pr_err("error %d getting APIC IRQ %d\n", irq, data->index);
0108
0109 return irq;
0110 case X86_ACPI_IRQ_TYPE_GPIOINT:
0111
0112 ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod);
0113 if (ret)
0114 return ret;
0115
0116 irq = gpiod_to_irq(gpiod);
0117 if (irq < 0) {
0118 pr_err("error %d getting IRQ %s %d\n", irq, data->chip, data->index);
0119 return irq;
0120 }
0121
0122 irq_type = acpi_dev_get_irq_type(data->trigger, data->polarity);
0123 if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq))
0124 irq_set_irq_type(irq, irq_type);
0125
0126 return irq;
0127 case X86_ACPI_IRQ_TYPE_PMIC:
0128 status = acpi_get_handle(NULL, data->chip, &handle);
0129 if (ACPI_FAILURE(status)) {
0130 pr_err("error could not get %s handle\n", data->chip);
0131 return -ENODEV;
0132 }
0133
0134 adev = acpi_fetch_acpi_dev(handle);
0135 if (!adev) {
0136 pr_err("error could not get %s adev\n", data->chip);
0137 return -ENODEV;
0138 }
0139
0140 fwspec.fwnode = acpi_fwnode_handle(adev);
0141 domain = irq_find_matching_fwspec(&fwspec, data->domain);
0142 if (!domain) {
0143 pr_err("error could not find IRQ domain for %s\n", data->chip);
0144 return -ENODEV;
0145 }
0146
0147 return irq_create_mapping(domain, data->index);
0148 default:
0149 return 0;
0150 }
0151 }
0152
0153 struct x86_i2c_client_info {
0154 struct i2c_board_info board_info;
0155 char *adapter_path;
0156 struct x86_acpi_irq_data irq_data;
0157 };
0158
0159 struct x86_serdev_info {
0160 const char *ctrl_hid;
0161 const char *ctrl_uid;
0162 const char *ctrl_devname;
0163
0164
0165
0166
0167
0168
0169 const char *serdev_hid;
0170 };
0171
0172 struct x86_dev_info {
0173 char *invalid_aei_gpiochip;
0174 const char * const *modules;
0175 const struct software_node *bat_swnode;
0176 struct gpiod_lookup_table * const *gpiod_lookup_tables;
0177 const struct x86_i2c_client_info *i2c_client_info;
0178 const struct platform_device_info *pdev_info;
0179 const struct x86_serdev_info *serdev_info;
0180 int i2c_client_count;
0181 int pdev_count;
0182 int serdev_count;
0183 int (*init)(void);
0184 void (*exit)(void);
0185 };
0186
0187
0188 static const char * const tusb1211_chg_det_psy[] = { "tusb1211-charger-detect" };
0189 static const char * const bq24190_psy[] = { "bq24190-charger" };
0190 static const char * const bq25890_psy[] = { "bq25890-charger" };
0191
0192 static const struct property_entry fg_bq24190_supply_props[] = {
0193 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
0194 { }
0195 };
0196
0197 static const struct software_node fg_bq24190_supply_node = {
0198 .properties = fg_bq24190_supply_props,
0199 };
0200
0201 static const struct property_entry fg_bq25890_supply_props[] = {
0202 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_psy),
0203 { }
0204 };
0205
0206 static const struct software_node fg_bq25890_supply_node = {
0207 .properties = fg_bq25890_supply_props,
0208 };
0209
0210
0211 static const struct property_entry generic_lipo_hv_4v35_battery_props[] = {
0212 PROPERTY_ENTRY_STRING("compatible", "simple-battery"),
0213 PROPERTY_ENTRY_STRING("device-chemistry", "lithium-ion"),
0214 PROPERTY_ENTRY_U32("precharge-current-microamp", 256000),
0215 PROPERTY_ENTRY_U32("charge-term-current-microamp", 128000),
0216 PROPERTY_ENTRY_U32("constant-charge-current-max-microamp", 1856000),
0217 PROPERTY_ENTRY_U32("constant-charge-voltage-max-microvolt", 4352000),
0218 PROPERTY_ENTRY_U32("factory-internal-resistance-micro-ohms", 150000),
0219 { }
0220 };
0221
0222 static const struct software_node generic_lipo_hv_4v35_battery_node = {
0223 .properties = generic_lipo_hv_4v35_battery_props,
0224 };
0225
0226
0227 static struct regulator_consumer_supply intel_int3496_consumer = {
0228 .supply = "vbus",
0229 .dev_name = "intel-int3496",
0230 };
0231
0232 static const struct regulator_init_data bq24190_vbus_init_data = {
0233 .constraints = {
0234 .name = "bq24190_vbus",
0235 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
0236 },
0237 .consumer_supplies = &intel_int3496_consumer,
0238 .num_consumer_supplies = 1,
0239 };
0240
0241 static struct bq24190_platform_data bq24190_pdata = {
0242 .regulator_init_data = &bq24190_vbus_init_data,
0243 };
0244
0245 static const char * const bq24190_modules[] __initconst = {
0246 "intel_crystal_cove_charger",
0247 "bq24190_charger",
0248 NULL
0249 };
0250
0251
0252 static const struct platform_device_info int3496_pdevs[] __initconst = {
0253 {
0254
0255 .name = "intel-int3496",
0256 .id = PLATFORM_DEVID_NONE,
0257 },
0258 };
0259
0260 static struct gpiod_lookup_table int3496_gpo2_pin22_gpios = {
0261 .dev_id = "intel-int3496",
0262 .table = {
0263 GPIO_LOOKUP("INT33FC:02", 22, "id", GPIO_ACTIVE_HIGH),
0264 { }
0265 },
0266 };
0267
0268
0269 static struct gpio_keys_button asus_me176c_tf103c_lid = {
0270 .code = SW_LID,
0271
0272 .active_low = true,
0273 .desc = "lid_sw",
0274 .type = EV_SW,
0275 .wakeup = true,
0276 .debounce_interval = 50,
0277 };
0278
0279 static const struct gpio_keys_platform_data asus_me176c_tf103c_lid_pdata __initconst = {
0280 .buttons = &asus_me176c_tf103c_lid,
0281 .nbuttons = 1,
0282 .name = "lid_sw",
0283 };
0284
0285 static const struct platform_device_info asus_me176c_tf103c_pdevs[] __initconst = {
0286 {
0287 .name = "gpio-keys",
0288 .id = PLATFORM_DEVID_AUTO,
0289 .data = &asus_me176c_tf103c_lid_pdata,
0290 .size_data = sizeof(asus_me176c_tf103c_lid_pdata),
0291 },
0292 {
0293
0294 .name = "intel-int3496",
0295 .id = PLATFORM_DEVID_NONE,
0296 },
0297 };
0298
0299 static int __init asus_me176c_tf103c_init(void)
0300 {
0301 struct gpio_desc *gpiod;
0302 int ret;
0303
0304 ret = x86_android_tablet_get_gpiod("INT33FC:02", 12, &gpiod);
0305 if (ret < 0)
0306 return ret;
0307 asus_me176c_tf103c_lid.gpio = desc_to_gpio(gpiod);
0308
0309 return 0;
0310 }
0311
0312
0313
0314 static const char * const asus_me176c_accel_mount_matrix[] = {
0315 "-1", "0", "0",
0316 "0", "1", "0",
0317 "0", "0", "1"
0318 };
0319
0320 static const struct property_entry asus_me176c_accel_props[] = {
0321 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", asus_me176c_accel_mount_matrix),
0322 { }
0323 };
0324
0325 static const struct software_node asus_me176c_accel_node = {
0326 .properties = asus_me176c_accel_props,
0327 };
0328
0329 static const struct property_entry asus_me176c_bq24190_props[] = {
0330 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
0331 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
0332 PROPERTY_ENTRY_U32("ti,system-minimum-microvolt", 3600000),
0333 PROPERTY_ENTRY_BOOL("omit-battery-class"),
0334 PROPERTY_ENTRY_BOOL("disable-reset"),
0335 { }
0336 };
0337
0338 static const struct software_node asus_me176c_bq24190_node = {
0339 .properties = asus_me176c_bq24190_props,
0340 };
0341
0342 static const struct property_entry asus_me176c_ug3105_props[] = {
0343 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
0344 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
0345 PROPERTY_ENTRY_U32("upisemi,rsns-microohm", 10000),
0346 { }
0347 };
0348
0349 static const struct software_node asus_me176c_ug3105_node = {
0350 .properties = asus_me176c_ug3105_props,
0351 };
0352
0353 static const struct x86_i2c_client_info asus_me176c_i2c_clients[] __initconst = {
0354 {
0355
0356 .board_info = {
0357 .type = "bq24190",
0358 .addr = 0x6b,
0359 .dev_name = "bq24297",
0360 .swnode = &asus_me176c_bq24190_node,
0361 .platform_data = &bq24190_pdata,
0362 },
0363 .adapter_path = "\\_SB_.I2C1",
0364 .irq_data = {
0365 .type = X86_ACPI_IRQ_TYPE_PMIC,
0366 .chip = "\\_SB_.I2C7.PMIC",
0367 .domain = DOMAIN_BUS_WAKEUP,
0368 .index = 0,
0369 },
0370 }, {
0371
0372 .board_info = {
0373 .type = "ug3105",
0374 .addr = 0x70,
0375 .dev_name = "ug3105",
0376 .swnode = &asus_me176c_ug3105_node,
0377 },
0378 .adapter_path = "\\_SB_.I2C1",
0379 }, {
0380
0381 .board_info = {
0382 .type = "ak09911",
0383 .addr = 0x0c,
0384 .dev_name = "ak09911",
0385 },
0386 .adapter_path = "\\_SB_.I2C5",
0387 }, {
0388
0389 .board_info = {
0390 .type = "kxtj21009",
0391 .addr = 0x0f,
0392 .dev_name = "kxtj21009",
0393 .swnode = &asus_me176c_accel_node,
0394 },
0395 .adapter_path = "\\_SB_.I2C5",
0396 .irq_data = {
0397 .type = X86_ACPI_IRQ_TYPE_APIC,
0398 .index = 0x44,
0399 .trigger = ACPI_EDGE_SENSITIVE,
0400 .polarity = ACPI_ACTIVE_LOW,
0401 },
0402 }, {
0403
0404 .board_info = {
0405 .type = "GDIX1001:00",
0406 .addr = 0x14,
0407 .dev_name = "goodix_ts",
0408 },
0409 .adapter_path = "\\_SB_.I2C6",
0410 .irq_data = {
0411 .type = X86_ACPI_IRQ_TYPE_APIC,
0412 .index = 0x45,
0413 .trigger = ACPI_EDGE_SENSITIVE,
0414 .polarity = ACPI_ACTIVE_LOW,
0415 },
0416 },
0417 };
0418
0419 static const struct x86_serdev_info asus_me176c_serdevs[] __initconst = {
0420 {
0421 .ctrl_hid = "80860F0A",
0422 .ctrl_uid = "2",
0423 .ctrl_devname = "serial0",
0424 .serdev_hid = "BCM2E3A",
0425 },
0426 };
0427
0428 static struct gpiod_lookup_table asus_me176c_goodix_gpios = {
0429 .dev_id = "i2c-goodix_ts",
0430 .table = {
0431 GPIO_LOOKUP("INT33FC:00", 60, "reset", GPIO_ACTIVE_HIGH),
0432 GPIO_LOOKUP("INT33FC:02", 28, "irq", GPIO_ACTIVE_HIGH),
0433 { }
0434 },
0435 };
0436
0437 static struct gpiod_lookup_table * const asus_me176c_gpios[] = {
0438 &int3496_gpo2_pin22_gpios,
0439 &asus_me176c_goodix_gpios,
0440 NULL
0441 };
0442
0443 static const struct x86_dev_info asus_me176c_info __initconst = {
0444 .i2c_client_info = asus_me176c_i2c_clients,
0445 .i2c_client_count = ARRAY_SIZE(asus_me176c_i2c_clients),
0446 .pdev_info = asus_me176c_tf103c_pdevs,
0447 .pdev_count = ARRAY_SIZE(asus_me176c_tf103c_pdevs),
0448 .serdev_info = asus_me176c_serdevs,
0449 .serdev_count = ARRAY_SIZE(asus_me176c_serdevs),
0450 .gpiod_lookup_tables = asus_me176c_gpios,
0451 .bat_swnode = &generic_lipo_hv_4v35_battery_node,
0452 .modules = bq24190_modules,
0453 .invalid_aei_gpiochip = "INT33FC:02",
0454 .init = asus_me176c_tf103c_init,
0455 };
0456
0457
0458 static const char * const asus_tf103c_accel_mount_matrix[] = {
0459 "0", "-1", "0",
0460 "-1", "0", "0",
0461 "0", "0", "1"
0462 };
0463
0464 static const struct property_entry asus_tf103c_accel_props[] = {
0465 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", asus_tf103c_accel_mount_matrix),
0466 { }
0467 };
0468
0469 static const struct software_node asus_tf103c_accel_node = {
0470 .properties = asus_tf103c_accel_props,
0471 };
0472
0473 static const struct property_entry asus_tf103c_touchscreen_props[] = {
0474 PROPERTY_ENTRY_STRING("compatible", "atmel,atmel_mxt_ts"),
0475 { }
0476 };
0477
0478 static const struct software_node asus_tf103c_touchscreen_node = {
0479 .properties = asus_tf103c_touchscreen_props,
0480 };
0481
0482 static const struct property_entry asus_tf103c_battery_props[] = {
0483 PROPERTY_ENTRY_STRING("compatible", "simple-battery"),
0484 PROPERTY_ENTRY_STRING("device-chemistry", "lithium-ion-polymer"),
0485 PROPERTY_ENTRY_U32("precharge-current-microamp", 256000),
0486 PROPERTY_ENTRY_U32("charge-term-current-microamp", 128000),
0487 PROPERTY_ENTRY_U32("constant-charge-current-max-microamp", 2048000),
0488 PROPERTY_ENTRY_U32("constant-charge-voltage-max-microvolt", 4208000),
0489 PROPERTY_ENTRY_U32("factory-internal-resistance-micro-ohms", 150000),
0490 { }
0491 };
0492
0493 static const struct software_node asus_tf103c_battery_node = {
0494 .properties = asus_tf103c_battery_props,
0495 };
0496
0497 static const struct property_entry asus_tf103c_bq24190_props[] = {
0498 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
0499 PROPERTY_ENTRY_REF("monitored-battery", &asus_tf103c_battery_node),
0500 PROPERTY_ENTRY_U32("ti,system-minimum-microvolt", 3600000),
0501 PROPERTY_ENTRY_BOOL("omit-battery-class"),
0502 PROPERTY_ENTRY_BOOL("disable-reset"),
0503 { }
0504 };
0505
0506 static const struct software_node asus_tf103c_bq24190_node = {
0507 .properties = asus_tf103c_bq24190_props,
0508 };
0509
0510 static const struct property_entry asus_tf103c_ug3105_props[] = {
0511 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
0512 PROPERTY_ENTRY_REF("monitored-battery", &asus_tf103c_battery_node),
0513 PROPERTY_ENTRY_U32("upisemi,rsns-microohm", 5000),
0514 { }
0515 };
0516
0517 static const struct software_node asus_tf103c_ug3105_node = {
0518 .properties = asus_tf103c_ug3105_props,
0519 };
0520
0521 static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst = {
0522 {
0523
0524 .board_info = {
0525 .type = "bq24190",
0526 .addr = 0x6b,
0527 .dev_name = "bq24297",
0528 .swnode = &asus_tf103c_bq24190_node,
0529 .platform_data = &bq24190_pdata,
0530 },
0531 .adapter_path = "\\_SB_.I2C1",
0532 .irq_data = {
0533 .type = X86_ACPI_IRQ_TYPE_PMIC,
0534 .chip = "\\_SB_.I2C7.PMIC",
0535 .domain = DOMAIN_BUS_WAKEUP,
0536 .index = 0,
0537 },
0538 }, {
0539
0540 .board_info = {
0541 .type = "ug3105",
0542 .addr = 0x70,
0543 .dev_name = "ug3105",
0544 .swnode = &asus_tf103c_ug3105_node,
0545 },
0546 .adapter_path = "\\_SB_.I2C1",
0547 }, {
0548
0549 .board_info = {
0550 .type = "ak09911",
0551 .addr = 0x0c,
0552 .dev_name = "ak09911",
0553 },
0554 .adapter_path = "\\_SB_.I2C5",
0555 }, {
0556
0557 .board_info = {
0558 .type = "kxtj21009",
0559 .addr = 0x0f,
0560 .dev_name = "kxtj21009",
0561 .swnode = &asus_tf103c_accel_node,
0562 },
0563 .adapter_path = "\\_SB_.I2C5",
0564 }, {
0565
0566 .board_info = {
0567 .type = "atmel_mxt_ts",
0568 .addr = 0x4a,
0569 .dev_name = "atmel_mxt_ts",
0570 .swnode = &asus_tf103c_touchscreen_node,
0571 },
0572 .adapter_path = "\\_SB_.I2C6",
0573 .irq_data = {
0574 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
0575 .chip = "INT33FC:02",
0576 .index = 28,
0577 .trigger = ACPI_EDGE_SENSITIVE,
0578 .polarity = ACPI_ACTIVE_LOW,
0579 },
0580 },
0581 };
0582
0583 static struct gpiod_lookup_table * const asus_tf103c_gpios[] = {
0584 &int3496_gpo2_pin22_gpios,
0585 NULL
0586 };
0587
0588 static const struct x86_dev_info asus_tf103c_info __initconst = {
0589 .i2c_client_info = asus_tf103c_i2c_clients,
0590 .i2c_client_count = ARRAY_SIZE(asus_tf103c_i2c_clients),
0591 .pdev_info = asus_me176c_tf103c_pdevs,
0592 .pdev_count = ARRAY_SIZE(asus_me176c_tf103c_pdevs),
0593 .gpiod_lookup_tables = asus_tf103c_gpios,
0594 .bat_swnode = &asus_tf103c_battery_node,
0595 .modules = bq24190_modules,
0596 .invalid_aei_gpiochip = "INT33FC:02",
0597 .init = asus_me176c_tf103c_init,
0598 };
0599
0600
0601
0602
0603
0604
0605 static const struct property_entry chuwi_hi8_gsl1680_props[] = {
0606 PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
0607 PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
0608 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
0609 PROPERTY_ENTRY_BOOL("silead,home-button"),
0610 PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"),
0611 { }
0612 };
0613
0614 static const struct software_node chuwi_hi8_gsl1680_node = {
0615 .properties = chuwi_hi8_gsl1680_props,
0616 };
0617
0618 static const char * const chuwi_hi8_mount_matrix[] = {
0619 "1", "0", "0",
0620 "0", "-1", "0",
0621 "0", "0", "1"
0622 };
0623
0624 static const struct property_entry chuwi_hi8_bma250e_props[] = {
0625 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", chuwi_hi8_mount_matrix),
0626 { }
0627 };
0628
0629 static const struct software_node chuwi_hi8_bma250e_node = {
0630 .properties = chuwi_hi8_bma250e_props,
0631 };
0632
0633 static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = {
0634 {
0635
0636 .board_info = {
0637 .type = "gsl1680",
0638 .addr = 0x40,
0639 .swnode = &chuwi_hi8_gsl1680_node,
0640 },
0641 .adapter_path = "\\_SB_.I2C4",
0642 .irq_data = {
0643 .type = X86_ACPI_IRQ_TYPE_APIC,
0644 .index = 0x44,
0645 .trigger = ACPI_EDGE_SENSITIVE,
0646 .polarity = ACPI_ACTIVE_HIGH,
0647 },
0648 }, {
0649
0650 .board_info = {
0651 .type = "bma250e",
0652 .addr = 0x18,
0653 .swnode = &chuwi_hi8_bma250e_node,
0654 },
0655 .adapter_path = "\\_SB_.I2C3",
0656 .irq_data = {
0657 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
0658 .chip = "INT33FC:02",
0659 .index = 23,
0660 .trigger = ACPI_LEVEL_SENSITIVE,
0661 .polarity = ACPI_ACTIVE_HIGH,
0662 },
0663 },
0664 };
0665
0666 static int __init chuwi_hi8_init(void)
0667 {
0668
0669
0670
0671
0672
0673 if (acpi_dev_present("MSSL0001", NULL, 1))
0674 return -ENODEV;
0675
0676 return 0;
0677 }
0678
0679 static const struct x86_dev_info chuwi_hi8_info __initconst = {
0680 .i2c_client_info = chuwi_hi8_i2c_clients,
0681 .i2c_client_count = ARRAY_SIZE(chuwi_hi8_i2c_clients),
0682 .init = chuwi_hi8_init,
0683 };
0684
0685 #define CZC_EC_EXTRA_PORT 0x68
0686 #define CZC_EC_ANDROID_KEYS 0x63
0687
0688 static int __init czc_p10t_init(void)
0689 {
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710 outb(CZC_EC_ANDROID_KEYS, CZC_EC_EXTRA_PORT);
0711 return 0;
0712 }
0713
0714 static const struct x86_dev_info czc_p10t __initconst = {
0715 .init = czc_p10t_init,
0716 };
0717
0718
0719 static const struct x86_i2c_client_info lenovo_yogabook_x9x_i2c_clients[] __initconst = {
0720 {
0721
0722 .board_info = {
0723 .type = "bq27542",
0724 .addr = 0x55,
0725 .dev_name = "bq27542",
0726 .swnode = &fg_bq25890_supply_node,
0727 },
0728 .adapter_path = "\\_SB_.PCI0.I2C1",
0729 },
0730 };
0731
0732 static const struct x86_dev_info lenovo_yogabook_x9x_info __initconst = {
0733 .i2c_client_info = lenovo_yogabook_x9x_i2c_clients,
0734 .i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x9x_i2c_clients),
0735 };
0736
0737
0738 static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
0739 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
0740 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
0741 PROPERTY_ENTRY_BOOL("omit-battery-class"),
0742 PROPERTY_ENTRY_BOOL("disable-reset"),
0743 { }
0744 };
0745
0746 static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
0747 .properties = lenovo_yoga_tab2_830_1050_bq24190_props,
0748 };
0749
0750
0751 static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
0752
0753 static struct lp855x_platform_data lenovo_yoga_tab2_830_1050_lp8557_pdata = {
0754 .device_control = 0x86,
0755 .initial_brightness = 128,
0756 };
0757
0758 static const struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initconst = {
0759 {
0760
0761 .board_info = {
0762 .type = "bq24190",
0763 .addr = 0x6b,
0764 .dev_name = "bq24292i",
0765 .swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
0766 .platform_data = &bq24190_pdata,
0767 },
0768 .adapter_path = "\\_SB_.I2C1",
0769 .irq_data = {
0770 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
0771 .chip = "INT33FC:02",
0772 .index = 2,
0773 .trigger = ACPI_EDGE_SENSITIVE,
0774 .polarity = ACPI_ACTIVE_HIGH,
0775 },
0776 }, {
0777
0778 .board_info = {
0779 .type = "bq27541",
0780 .addr = 0x55,
0781 .dev_name = "bq27541",
0782 .swnode = &fg_bq24190_supply_node,
0783 },
0784 .adapter_path = "\\_SB_.I2C1",
0785 }, {
0786
0787 .board_info = {
0788 .type = "rmi4_i2c",
0789 .addr = 0x38,
0790 .dev_name = "rmi4_i2c",
0791 .platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
0792 },
0793 .adapter_path = "\\_SB_.I2C6",
0794 .irq_data = {
0795 .type = X86_ACPI_IRQ_TYPE_APIC,
0796 .index = 0x45,
0797 .trigger = ACPI_EDGE_SENSITIVE,
0798 .polarity = ACPI_ACTIVE_HIGH,
0799 },
0800 }, {
0801
0802 .board_info = {
0803 .type = "lp8557",
0804 .addr = 0x2c,
0805 .dev_name = "lp8557",
0806 .platform_data = &lenovo_yoga_tab2_830_1050_lp8557_pdata,
0807 },
0808 .adapter_path = "\\_SB_.I2C3",
0809 },
0810 };
0811
0812 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
0813 .dev_id = "intel-int3496",
0814 .table = {
0815 GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
0816 GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
0817 { }
0818 },
0819 };
0820
0821 #define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
0822
0823 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = {
0824 .dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME,
0825 .table = {
0826 GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH),
0827 GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH),
0828 GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
0829 GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW),
0830 { }
0831 },
0832 };
0833
0834 static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = {
0835 &lenovo_yoga_tab2_830_1050_int3496_gpios,
0836 &lenovo_yoga_tab2_830_1050_codec_gpios,
0837 NULL
0838 };
0839
0840 static int __init lenovo_yoga_tab2_830_1050_init(void);
0841 static void lenovo_yoga_tab2_830_1050_exit(void);
0842
0843 static struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initdata = {
0844 .i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
0845
0846 .pdev_info = int3496_pdevs,
0847 .pdev_count = ARRAY_SIZE(int3496_pdevs),
0848 .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
0849 .bat_swnode = &generic_lipo_hv_4v35_battery_node,
0850 .modules = bq24190_modules,
0851 .invalid_aei_gpiochip = "INT33FC:02",
0852 .init = lenovo_yoga_tab2_830_1050_init,
0853 .exit = lenovo_yoga_tab2_830_1050_exit,
0854 };
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874 static int __init lenovo_yoga_tab2_830_1050_init_display(void)
0875 {
0876 struct gpio_desc *gpiod;
0877 int ret;
0878
0879
0880 ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod);
0881 if (ret)
0882 return ret;
0883
0884 ret = gpiod_get_value_cansleep(gpiod);
0885 if (ret) {
0886 pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
0887 lenovo_yoga_tab2_830_1050_info.i2c_client_count =
0888 ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients) - 1;
0889 } else {
0890 pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
0891 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
0892 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
0893 lenovo_yoga_tab2_830_1050_info.i2c_client_count =
0894 ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients);
0895 }
0896
0897 return 0;
0898 }
0899
0900
0901 static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map =
0902 PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk",
0903 "INT33FC:02", "pmu_clk2_grp", "pmu_clk");
0904
0905 static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
0906 static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler;
0907
0908 static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
0909 {
0910 struct device *codec_dev;
0911 struct pinctrl *pinctrl;
0912 int ret;
0913
0914 codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
0915 LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
0916 if (!codec_dev) {
0917 pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
0918 return -ENODEV;
0919 }
0920
0921 ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
0922 if (ret)
0923 goto err_put_device;
0924
0925 pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk");
0926 if (IS_ERR(pinctrl)) {
0927 ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n");
0928 goto err_unregister_mappings;
0929 }
0930
0931
0932 put_device(codec_dev);
0933
0934 lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
0935 return 0;
0936
0937 err_unregister_mappings:
0938 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
0939 err_put_device:
0940 put_device(codec_dev);
0941 return ret;
0942 }
0943
0944
0945
0946
0947
0948
0949
0950
0951 static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data)
0952 {
0953 efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
0954
0955 return NOTIFY_DONE;
0956 }
0957
0958 static int __init lenovo_yoga_tab2_830_1050_init(void)
0959 {
0960 int ret;
0961
0962 ret = lenovo_yoga_tab2_830_1050_init_display();
0963 if (ret)
0964 return ret;
0965
0966 ret = lenovo_yoga_tab2_830_1050_init_codec();
0967 if (ret)
0968 return ret;
0969
0970
0971 lenovo_yoga_tab2_830_1050_sys_off_handler =
0972 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1,
0973 lenovo_yoga_tab2_830_1050_power_off, NULL);
0974 if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler))
0975 return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler);
0976
0977 return 0;
0978 }
0979
0980 static void lenovo_yoga_tab2_830_1050_exit(void)
0981 {
0982 unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler);
0983
0984 if (lenovo_yoga_tab2_830_1050_codec_pinctrl) {
0985 pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
0986 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
0987 }
0988 }
0989
0990
0991 static const char * const nextbook_ares8_accel_mount_matrix[] = {
0992 "0", "-1", "0",
0993 "-1", "0", "0",
0994 "0", "0", "1"
0995 };
0996
0997 static const struct property_entry nextbook_ares8_accel_props[] = {
0998 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", nextbook_ares8_accel_mount_matrix),
0999 { }
1000 };
1001
1002 static const struct software_node nextbook_ares8_accel_node = {
1003 .properties = nextbook_ares8_accel_props,
1004 };
1005
1006 static const struct property_entry nextbook_ares8_touchscreen_props[] = {
1007 PROPERTY_ENTRY_U32("touchscreen-size-x", 800),
1008 PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
1009 { }
1010 };
1011
1012 static const struct software_node nextbook_ares8_touchscreen_node = {
1013 .properties = nextbook_ares8_touchscreen_props,
1014 };
1015
1016 static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst = {
1017 {
1018
1019 .board_info = {
1020 .type = "mma8653",
1021 .addr = 0x1d,
1022 .dev_name = "mma8653",
1023 .swnode = &nextbook_ares8_accel_node,
1024 },
1025 .adapter_path = "\\_SB_.I2C3",
1026 }, {
1027
1028 .board_info = {
1029 .type = "edt-ft5x06",
1030 .addr = 0x38,
1031 .dev_name = "ft5416",
1032 .swnode = &nextbook_ares8_touchscreen_node,
1033 },
1034 .adapter_path = "\\_SB_.I2C4",
1035 .irq_data = {
1036 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
1037 .chip = "INT33FC:02",
1038 .index = 3,
1039 .trigger = ACPI_EDGE_SENSITIVE,
1040 .polarity = ACPI_ACTIVE_LOW,
1041 },
1042 },
1043 };
1044
1045 static struct gpiod_lookup_table nextbook_ares8_int3496_gpios = {
1046 .dev_id = "intel-int3496",
1047 .table = {
1048 GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_HIGH),
1049 GPIO_LOOKUP("INT33FC:02", 18, "id", GPIO_ACTIVE_HIGH),
1050 { }
1051 },
1052 };
1053
1054 static struct gpiod_lookup_table * const nextbook_ares8_gpios[] = {
1055 &nextbook_ares8_int3496_gpios,
1056 NULL
1057 };
1058
1059 static const struct x86_dev_info nextbook_ares8_info __initconst = {
1060 .i2c_client_info = nextbook_ares8_i2c_clients,
1061 .i2c_client_count = ARRAY_SIZE(nextbook_ares8_i2c_clients),
1062 .pdev_info = int3496_pdevs,
1063 .pdev_count = ARRAY_SIZE(int3496_pdevs),
1064 .gpiod_lookup_tables = nextbook_ares8_gpios,
1065 .invalid_aei_gpiochip = "INT33FC:02",
1066 };
1067
1068
1069
1070
1071
1072
1073
1074 static const char * const whitelabel_tm800a550l_accel_mount_matrix[] = {
1075 "-1", "0", "0",
1076 "0", "1", "0",
1077 "0", "0", "1"
1078 };
1079
1080 static const struct property_entry whitelabel_tm800a550l_accel_props[] = {
1081 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", whitelabel_tm800a550l_accel_mount_matrix),
1082 { }
1083 };
1084
1085 static const struct software_node whitelabel_tm800a550l_accel_node = {
1086 .properties = whitelabel_tm800a550l_accel_props,
1087 };
1088
1089 static const struct property_entry whitelabel_tm800a550l_goodix_props[] = {
1090 PROPERTY_ENTRY_STRING("firmware-name", "gt912-tm800a550l.fw"),
1091 PROPERTY_ENTRY_STRING("goodix,config-name", "gt912-tm800a550l.cfg"),
1092 PROPERTY_ENTRY_U32("goodix,main-clk", 54),
1093 { }
1094 };
1095
1096 static const struct software_node whitelabel_tm800a550l_goodix_node = {
1097 .properties = whitelabel_tm800a550l_goodix_props,
1098 };
1099
1100 static const struct x86_i2c_client_info whitelabel_tm800a550l_i2c_clients[] __initconst = {
1101 {
1102
1103 .board_info = {
1104 .type = "GDIX1001:00",
1105 .addr = 0x14,
1106 .dev_name = "goodix_ts",
1107 .swnode = &whitelabel_tm800a550l_goodix_node,
1108 },
1109 .adapter_path = "\\_SB_.I2C2",
1110 .irq_data = {
1111 .type = X86_ACPI_IRQ_TYPE_APIC,
1112 .index = 0x44,
1113 .trigger = ACPI_EDGE_SENSITIVE,
1114 .polarity = ACPI_ACTIVE_HIGH,
1115 },
1116 }, {
1117
1118 .board_info = {
1119 .type = "kxcj91008",
1120 .addr = 0x0f,
1121 .dev_name = "kxcj91008",
1122 .swnode = &whitelabel_tm800a550l_accel_node,
1123 },
1124 .adapter_path = "\\_SB_.I2C3",
1125 },
1126 };
1127
1128 static struct gpiod_lookup_table whitelabel_tm800a550l_goodix_gpios = {
1129 .dev_id = "i2c-goodix_ts",
1130 .table = {
1131 GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_HIGH),
1132 GPIO_LOOKUP("INT33FC:02", 3, "irq", GPIO_ACTIVE_HIGH),
1133 { }
1134 },
1135 };
1136
1137 static struct gpiod_lookup_table * const whitelabel_tm800a550l_gpios[] = {
1138 &whitelabel_tm800a550l_goodix_gpios,
1139 NULL
1140 };
1141
1142 static const struct x86_dev_info whitelabel_tm800a550l_info __initconst = {
1143 .i2c_client_info = whitelabel_tm800a550l_i2c_clients,
1144 .i2c_client_count = ARRAY_SIZE(whitelabel_tm800a550l_i2c_clients),
1145 .gpiod_lookup_tables = whitelabel_tm800a550l_gpios,
1146 };
1147
1148
1149
1150
1151
1152
1153
1154
1155 static const struct x86_i2c_client_info xiaomi_mipad2_i2c_clients[] __initconst = {
1156 {
1157
1158 .board_info = {
1159 .type = "bq27520",
1160 .addr = 0x55,
1161 .dev_name = "bq27520",
1162 .swnode = &fg_bq25890_supply_node,
1163 },
1164 .adapter_path = "\\_SB_.PCI0.I2C1",
1165 }, {
1166
1167 .board_info = {
1168 .type = "ktd2026",
1169 .addr = 0x30,
1170 .dev_name = "ktd2026",
1171 },
1172 .adapter_path = "\\_SB_.PCI0.I2C3",
1173 },
1174 };
1175
1176 static const struct x86_dev_info xiaomi_mipad2_info __initconst = {
1177 .i2c_client_info = xiaomi_mipad2_i2c_clients,
1178 .i2c_client_count = ARRAY_SIZE(xiaomi_mipad2_i2c_clients),
1179 };
1180
1181 static const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
1182 {
1183
1184 .matches = {
1185 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1186 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
1187 },
1188 .driver_data = (void *)&asus_me176c_info,
1189 },
1190 {
1191
1192 .matches = {
1193 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1194 DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
1195 },
1196 .driver_data = (void *)&asus_tf103c_info,
1197 },
1198 {
1199
1200 .matches = {
1201 DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
1202 DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"),
1203 DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
1204 DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
1205 },
1206 .driver_data = (void *)&chuwi_hi8_info,
1207 },
1208 {
1209
1210 .ident = "CZC ODEON TPC-10 (\"P10T\")",
1211 .matches = {
1212 DMI_MATCH(DMI_SYS_VENDOR, "CZC"),
1213 DMI_MATCH(DMI_PRODUCT_NAME, "ODEON*TPC-10"),
1214 },
1215 .driver_data = (void *)&czc_p10t,
1216 },
1217 {
1218
1219 .ident = "ViewSonic ViewPad 10",
1220 .matches = {
1221 DMI_MATCH(DMI_SYS_VENDOR, "ViewSonic"),
1222 DMI_MATCH(DMI_PRODUCT_NAME, "VPAD10"),
1223 },
1224 .driver_data = (void *)&czc_p10t,
1225 },
1226 {
1227
1228 .matches = {
1229
1230 DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
1231 },
1232 .driver_data = (void *)&lenovo_yogabook_x9x_info,
1233 },
1234 {
1235
1236
1237
1238
1239 .matches = {
1240 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
1241 DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
1242 DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
1243
1244 DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
1245 },
1246 .driver_data = (void *)&lenovo_yoga_tab2_830_1050_info,
1247 },
1248 {
1249
1250 .matches = {
1251 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
1252 DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
1253 },
1254 .driver_data = (void *)&nextbook_ares8_info,
1255 },
1256 {
1257
1258 .matches = {
1259 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
1260 DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
1261
1262 DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
1263 },
1264 .driver_data = (void *)&whitelabel_tm800a550l_info,
1265 },
1266 {
1267
1268 .matches = {
1269 DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
1270 DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
1271 },
1272 .driver_data = (void *)&xiaomi_mipad2_info,
1273 },
1274 { }
1275 };
1276 MODULE_DEVICE_TABLE(dmi, x86_android_tablet_ids);
1277
1278 static int i2c_client_count;
1279 static int pdev_count;
1280 static int serdev_count;
1281 static struct i2c_client **i2c_clients;
1282 static struct platform_device **pdevs;
1283 static struct serdev_device **serdevs;
1284 static struct gpiod_lookup_table * const *gpiod_lookup_tables;
1285 static const struct software_node *bat_swnode;
1286 static void (*exit_handler)(void);
1287
1288 static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info,
1289 int idx)
1290 {
1291 const struct x86_i2c_client_info *client_info = &dev_info->i2c_client_info[idx];
1292 struct i2c_board_info board_info = client_info->board_info;
1293 struct i2c_adapter *adap;
1294 acpi_handle handle;
1295 acpi_status status;
1296
1297 board_info.irq = x86_acpi_irq_helper_get(&client_info->irq_data);
1298 if (board_info.irq < 0)
1299 return board_info.irq;
1300
1301 status = acpi_get_handle(NULL, client_info->adapter_path, &handle);
1302 if (ACPI_FAILURE(status)) {
1303 pr_err("Error could not get %s handle\n", client_info->adapter_path);
1304 return -ENODEV;
1305 }
1306
1307 adap = i2c_acpi_find_adapter_by_handle(handle);
1308 if (!adap) {
1309 pr_err("error could not get %s adapter\n", client_info->adapter_path);
1310 return -ENODEV;
1311 }
1312
1313 i2c_clients[idx] = i2c_new_client_device(adap, &board_info);
1314 put_device(&adap->dev);
1315 if (IS_ERR(i2c_clients[idx]))
1316 return dev_err_probe(&adap->dev, PTR_ERR(i2c_clients[idx]),
1317 "creating I2C-client %d\n", idx);
1318
1319 return 0;
1320 }
1321
1322 static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx)
1323 {
1324 struct acpi_device *ctrl_adev, *serdev_adev;
1325 struct serdev_device *serdev;
1326 struct device *ctrl_dev;
1327 int ret = -ENODEV;
1328
1329 ctrl_adev = acpi_dev_get_first_match_dev(info->ctrl_hid, info->ctrl_uid, -1);
1330 if (!ctrl_adev) {
1331 pr_err("error could not get %s/%s ctrl adev\n",
1332 info->ctrl_hid, info->ctrl_uid);
1333 return -ENODEV;
1334 }
1335
1336 serdev_adev = acpi_dev_get_first_match_dev(info->serdev_hid, NULL, -1);
1337 if (!serdev_adev) {
1338 pr_err("error could not get %s serdev adev\n", info->serdev_hid);
1339 goto put_ctrl_adev;
1340 }
1341
1342
1343 ctrl_dev = acpi_get_first_physical_node(ctrl_adev);
1344 if (!ctrl_dev) {
1345 pr_err("error could not get %s/%s ctrl physical dev\n",
1346 info->ctrl_hid, info->ctrl_uid);
1347 goto put_serdev_adev;
1348 }
1349
1350
1351 ctrl_dev = device_find_child_by_name(ctrl_dev, info->ctrl_devname);
1352 if (!ctrl_dev) {
1353 pr_err("error could not get %s/%s %s ctrl dev\n",
1354 info->ctrl_hid, info->ctrl_uid, info->ctrl_devname);
1355 goto put_serdev_adev;
1356 }
1357
1358 serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev));
1359 if (!serdev) {
1360 ret = -ENOMEM;
1361 goto put_serdev_adev;
1362 }
1363
1364 ACPI_COMPANION_SET(&serdev->dev, serdev_adev);
1365 acpi_device_set_enumerated(serdev_adev);
1366
1367 ret = serdev_device_add(serdev);
1368 if (ret) {
1369 dev_err(&serdev->dev, "error %d adding serdev\n", ret);
1370 serdev_device_put(serdev);
1371 goto put_serdev_adev;
1372 }
1373
1374 serdevs[idx] = serdev;
1375
1376 put_serdev_adev:
1377 acpi_dev_put(serdev_adev);
1378 put_ctrl_adev:
1379 acpi_dev_put(ctrl_adev);
1380 return ret;
1381 }
1382
1383 static void x86_android_tablet_cleanup(void)
1384 {
1385 int i;
1386
1387 for (i = 0; i < serdev_count; i++) {
1388 if (serdevs[i])
1389 serdev_device_remove(serdevs[i]);
1390 }
1391
1392 kfree(serdevs);
1393
1394 for (i = 0; i < pdev_count; i++)
1395 platform_device_unregister(pdevs[i]);
1396
1397 kfree(pdevs);
1398
1399 for (i = 0; i < i2c_client_count; i++)
1400 i2c_unregister_device(i2c_clients[i]);
1401
1402 kfree(i2c_clients);
1403
1404 if (exit_handler)
1405 exit_handler();
1406
1407 for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
1408 gpiod_remove_lookup_table(gpiod_lookup_tables[i]);
1409
1410 software_node_unregister(bat_swnode);
1411 }
1412
1413 static __init int x86_android_tablet_init(void)
1414 {
1415 const struct x86_dev_info *dev_info;
1416 const struct dmi_system_id *id;
1417 struct gpio_chip *chip;
1418 int i, ret = 0;
1419
1420 id = dmi_first_match(x86_android_tablet_ids);
1421 if (!id)
1422 return -ENODEV;
1423
1424 dev_info = id->driver_data;
1425
1426
1427
1428
1429
1430 if (dev_info->invalid_aei_gpiochip) {
1431 chip = gpiochip_find(dev_info->invalid_aei_gpiochip,
1432 gpiochip_find_match_label);
1433 if (!chip) {
1434 pr_err("error cannot find GPIO chip %s\n", dev_info->invalid_aei_gpiochip);
1435 return -ENODEV;
1436 }
1437 acpi_gpiochip_free_interrupts(chip);
1438 }
1439
1440
1441
1442
1443
1444 for (i = 0; dev_info->modules && dev_info->modules[i]; i++)
1445 request_module(dev_info->modules[i]);
1446
1447 bat_swnode = dev_info->bat_swnode;
1448 if (bat_swnode) {
1449 ret = software_node_register(bat_swnode);
1450 if (ret)
1451 return ret;
1452 }
1453
1454 gpiod_lookup_tables = dev_info->gpiod_lookup_tables;
1455 for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
1456 gpiod_add_lookup_table(gpiod_lookup_tables[i]);
1457
1458 if (dev_info->init) {
1459 ret = dev_info->init();
1460 if (ret < 0) {
1461 x86_android_tablet_cleanup();
1462 return ret;
1463 }
1464 exit_handler = dev_info->exit;
1465 }
1466
1467 i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL);
1468 if (!i2c_clients) {
1469 x86_android_tablet_cleanup();
1470 return -ENOMEM;
1471 }
1472
1473 i2c_client_count = dev_info->i2c_client_count;
1474 for (i = 0; i < i2c_client_count; i++) {
1475 ret = x86_instantiate_i2c_client(dev_info, i);
1476 if (ret < 0) {
1477 x86_android_tablet_cleanup();
1478 return ret;
1479 }
1480 }
1481
1482 pdevs = kcalloc(dev_info->pdev_count, sizeof(*pdevs), GFP_KERNEL);
1483 if (!pdevs) {
1484 x86_android_tablet_cleanup();
1485 return -ENOMEM;
1486 }
1487
1488 pdev_count = dev_info->pdev_count;
1489 for (i = 0; i < pdev_count; i++) {
1490 pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]);
1491 if (IS_ERR(pdevs[i])) {
1492 x86_android_tablet_cleanup();
1493 return PTR_ERR(pdevs[i]);
1494 }
1495 }
1496
1497 serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL);
1498 if (!serdevs) {
1499 x86_android_tablet_cleanup();
1500 return -ENOMEM;
1501 }
1502
1503 serdev_count = dev_info->serdev_count;
1504 for (i = 0; i < serdev_count; i++) {
1505 ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i);
1506 if (ret < 0) {
1507 x86_android_tablet_cleanup();
1508 return ret;
1509 }
1510 }
1511
1512 return 0;
1513 }
1514
1515 module_init(x86_android_tablet_init);
1516 module_exit(x86_android_tablet_cleanup);
1517
1518 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
1519 MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver");
1520 MODULE_LICENSE("GPL");