[PATCH 1/2] platform/x86: intel_cht_int33fe: Register battery fuel gauge only for Yoga Book

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Lenovo Yoga Book has INT33FE definition in the ACPI DSDT but doesn't
have USB TypeC connector and muxer (it uses micro USB).

Add I2C device definition for BQ27542 battery fuel gauge used in this
notebook and register only it.

Signed-off-by: Yauhen Kharuzhy <jekhor@xxxxxxxxx>
---
 drivers/platform/x86/intel_cht_int33fe.c | 67 +++++++++++++++++++-----
 1 file changed, 55 insertions(+), 12 deletions(-)

diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c
index 02bc74608cf3..6e8ef485f0b1 100644
--- a/drivers/platform/x86/intel_cht_int33fe.c
+++ b/drivers/platform/x86/intel_cht_int33fe.c
@@ -24,11 +24,12 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 
 #define EXPECTED_PTYPE		4
 
 struct cht_int33fe_data {
-	struct i2c_client *max17047;
+	struct i2c_client *battery_fg;
 	struct i2c_client *fusb302;
 	struct i2c_client *pi3usb30532;
 	/* Contain a list-head must be per device */
@@ -78,6 +79,12 @@ static const struct property_entry max17047_props[] = {
 	{ }
 };
 
+static const char * const bq27xxx_suppliers[] = { "bq25890-charger" };
+static const struct property_entry bq27xxx_props[] = {
+	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq27xxx_suppliers),
+	{ }
+};
+
 static const struct property_entry fusb302_props[] = {
 	PROPERTY_ENTRY_STRING("linux,extcon-name", "cht_wcove_pwrsrc"),
 	PROPERTY_ENTRY_U32("fcs,max-sink-microvolt", 12000000),
@@ -86,6 +93,17 @@ static const struct property_entry fusb302_props[] = {
 	{ }
 };
 
+static const struct dmi_system_id yogabook_ids[] = {
+	{
+		.ident = "Lenovo Yogabook",
+		/* YB1-X91L/F and YB1-X90L/F */
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9")
+		}
+	},
+	{}
+};
+
 static int cht_int33fe_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -97,6 +115,7 @@ static int cht_int33fe_probe(struct platform_device *pdev)
 	acpi_status status;
 	int fusb302_irq;
 	int ret;
+	const char *product_name;
 
 	status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp);
 	if (ACPI_FAILURE(status)) {
@@ -118,6 +137,29 @@ static int cht_int33fe_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/* Lenovo Yoga Book has INT33FE device in DSDT table but this device
+	 * doesn't have FUSB302, max17047 and pi3usb30532 definitions but has
+	 * a bq27542 battery gauge.
+	 */
+	product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (dmi_check_system(yogabook_ids)) {
+		dev_info(dev, "Lenovo Yoga Book detected, register only "
+				"BQ27542 battery Fuel Gauge for it\n");
+
+		memset(&board_info, 0, sizeof(board_info));
+		strlcpy(board_info.type, "bq27542", I2C_NAME_SIZE);
+		board_info.dev_name = "bq27542";
+		board_info.properties = bq27xxx_props;
+		data->battery_fg = i2c_acpi_new_device(dev, 1, &board_info);
+
+		goto done;
+	}
+
+
 	/*
 	 * We expect the WC PMIC to be paired with a TI bq24292i charger-IC.
 	 * We check for the bq24292i vbus regulator here, this has 2 purposes:
@@ -147,10 +189,6 @@ static int cht_int33fe_probe(struct platform_device *pdev)
 		return fusb302_irq;
 	}
 
-	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
 	/* Work around BIOS bug, see comment on cht_int33fe_find_max17047 */
 	max17047 = cht_int33fe_find_max17047();
 	if (max17047) {
@@ -167,9 +205,9 @@ static int cht_int33fe_probe(struct platform_device *pdev)
 		strlcpy(board_info.type, "max17047", I2C_NAME_SIZE);
 		board_info.dev_name = "max17047";
 		board_info.properties = max17047_props;
-		data->max17047 = i2c_acpi_new_device(dev, 1, &board_info);
-		if (IS_ERR(data->max17047))
-			return PTR_ERR(data->max17047);
+		data->battery_fg = i2c_acpi_new_device(dev, 1, &board_info);
+		if (IS_ERR(data->battery_fg))
+			return PTR_ERR(data->battery_fg);
 	}
 
 	data->connections[0].endpoint[0] = "port0";
@@ -209,6 +247,7 @@ static int cht_int33fe_probe(struct platform_device *pdev)
 		goto out_unregister_fusb302;
 	}
 
+done:
 	platform_set_drvdata(pdev, data);
 
 	return 0;
@@ -217,7 +256,7 @@ static int cht_int33fe_probe(struct platform_device *pdev)
 	i2c_unregister_device(data->fusb302);
 
 out_unregister_max17047:
-	i2c_unregister_device(data->max17047);
+	i2c_unregister_device(data->battery_fg);
 
 	device_connections_remove(data->connections);
 
@@ -228,9 +267,13 @@ static int cht_int33fe_remove(struct platform_device *pdev)
 {
 	struct cht_int33fe_data *data = platform_get_drvdata(pdev);
 
-	i2c_unregister_device(data->pi3usb30532);
-	i2c_unregister_device(data->fusb302);
-	i2c_unregister_device(data->max17047);
+	if (data->pi3usb30532)
+		i2c_unregister_device(data->pi3usb30532);
+
+	if (data->fusb302)
+		i2c_unregister_device(data->fusb302);
+
+	i2c_unregister_device(data->battery_fg);
 
 	device_connections_remove(data->connections);
 
-- 
2.20.1




[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux