platform/x86: x86-android-tablets: Add Lenovo Yoga Tab 3 (YT3-X90F) charger + fuel...
authorHans de Goede <hdegoede@redhat.com>
Sun, 27 Nov 2022 18:24:58 +0000 (19:24 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 7 Jan 2023 10:11:43 +0000 (11:11 +0100)
[ Upstream commit b6c14ff1deaafd30036ec36d5205acd5a578b1cd ]

The Lenovo Yoga Tab 3 (YT3-X90F) is an Intel Cherry Trail based tablet
which ships with Android as Factory OS. Its DSDT contains a bunch of I2C
devices which are not actually there, causing various resource conflicts.
Use acpi_quirk_skip_i2c_client_enumeration() to not enumerate these.

The YT3-X90F has quite a bit of exotic hardware, this adds initial
support by manually instantiating the i2c-clients for the 2 charger +
2 fuel-gauge chips used for the 2 batteries.

Support for other parts of the hw will be added by follow-up patches.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20221127182458.104528-1-hdegoede@redhat.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/platform/x86/x86-android-tablets.c

index f04e06e..bbfae13 100644 (file)
@@ -5,7 +5,7 @@
  * devices typically have a bunch of things hardcoded, rather than specified
  * in their DSDT.
  *
- * Copyright (C) 2021 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (C) 2021-2022 Hans de Goede <hdegoede@redhat.com>
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -987,6 +987,130 @@ static void lenovo_yoga_tab2_830_1050_exit(void)
        }
 }
 
+/* Lenovo Yoga Tab 3 Pro YT3-X90F */
+
+/*
+ * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers,
+ * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c.
+ */
+static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
+static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
+
+static const struct property_entry fg_bq25890_1_supply_props[] = {
+       PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
+       { }
+};
+
+static const struct software_node fg_bq25890_1_supply_node = {
+       .properties = fg_bq25890_1_supply_props,
+};
+
+/* bq25892 charger settings for the flat lipo battery behind the screen */
+static const struct property_entry lenovo_yt3_bq25892_0_props[] = {
+       PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers),
+       PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"),
+       PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40),
+       PROPERTY_ENTRY_BOOL("linux,skip-reset"),
+       /* Values taken from Android Factory Image */
+       PROPERTY_ENTRY_U32("ti,charge-current", 2048000),
+       PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
+       PROPERTY_ENTRY_U32("ti,termination-current", 128000),
+       PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
+       PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000),
+       PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
+       PROPERTY_ENTRY_U32("ti,boost-max-current", 500000),
+       PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
+       { }
+};
+
+static const struct software_node lenovo_yt3_bq25892_0_node = {
+       .properties = lenovo_yt3_bq25892_0_props,
+};
+
+static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
+       {
+               /* bq27500 fuel-gauge for the flat lipo battery behind the screen */
+               .board_info = {
+                       .type = "bq27500",
+                       .addr = 0x55,
+                       .dev_name = "bq27500_0",
+                       .swnode = &fg_bq25890_supply_node,
+               },
+               .adapter_path = "\\_SB_.PCI0.I2C1",
+       }, {
+               /* bq25892 charger for the flat lipo battery behind the screen */
+               .board_info = {
+                       .type = "bq25892",
+                       .addr = 0x6b,
+                       .dev_name = "bq25892_0",
+                       .swnode = &lenovo_yt3_bq25892_0_node,
+               },
+               .adapter_path = "\\_SB_.PCI0.I2C1",
+               .irq_data = {
+                       .type = X86_ACPI_IRQ_TYPE_GPIOINT,
+                       .chip = "INT33FF:01",
+                       .index = 5,
+                       .trigger = ACPI_EDGE_SENSITIVE,
+                       .polarity = ACPI_ACTIVE_LOW,
+               },
+       }, {
+               /* bq27500 fuel-gauge for the round li-ion cells in the hinge */
+               .board_info = {
+                       .type = "bq27500",
+                       .addr = 0x55,
+                       .dev_name = "bq27500_1",
+                       .swnode = &fg_bq25890_1_supply_node,
+               },
+               .adapter_path = "\\_SB_.PCI0.I2C2",
+       }
+};
+
+static int __init lenovo_yt3_init(void)
+{
+       struct gpio_desc *gpiod;
+       int ret;
+
+       /*
+        * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins
+        * connected to GPIOs, rather then having them hardwired to the correct
+        * values as is normally done.
+        *
+        * The bq25890_charger driver controls these through I2C, but this only
+        * works if not overridden by the pins. Set these pins here:
+        * 1. Set /CE to 0 to allow charging.
+        * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
+        *    the main "bq25892_1" charger is used when necessary.
+        */
+
+       /* /CE pin */
+       ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw"
+        * gpio_desc, that is there is no way to pass lookup-flags like
+        * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since
+        * the /CE pin is active-low, but not marked as such in the gpio_desc.
+        */
+       gpiod_set_value(gpiod, 0);
+
+       /* OTG pin */
+       ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod);
+       if (ret < 0)
+               return ret;
+
+       gpiod_set_value(gpiod, 0);
+
+       return 0;
+}
+
+static const struct x86_dev_info lenovo_yt3_info __initconst = {
+       .i2c_client_info = lenovo_yt3_i2c_clients,
+       .i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients),
+       .init = lenovo_yt3_init,
+};
+
 /* Medion Lifetab S10346 tablets have an Android factory img with everything hardcoded */
 static const char * const medion_lifetab_s10346_accel_mount_matrix[] = {
        "0", "1", "0",
@@ -1328,6 +1452,15 @@ static const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
                .driver_data = (void *)&lenovo_yoga_tab2_830_1050_info,
        },
        {
+               /* Lenovo Yoga Tab 3 Pro YT3-X90F */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
+               },
+               .driver_data = (void *)&lenovo_yt3_info,
+       },
+       {
                /* Medion Lifetab S10346 */
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),