Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

platform/x86: intel_cht_int33fe: Split code to Micro-B and Type-C

Existing intel_cht_int33fe ACPI pseudo-device driver assumes that
hardware has Type-C connector and register related devices described as
I2C connections in the _CRS resource.

There is at least one hardware (Lenovo Yoga Book YB1-91L/F) with Micro-B
USB connector exists. It has INT33FE device in the DSDT table but
there are only two I2C connection described: PMIC and BQ27452 battery
fuel gauge.

Splitting existing INT33FE driver allow to maintain code for USB Micro-B
(or AB) connector variant separately and make it simpler.

Split driver to intel_cht_int33fe_common.c and
intel_cht_int33fe_{microb,typec}.c. Compile all this sources to one .ko
module to make user experience easier.

Signed-off-by: Yauhen Kharuzhy <jekhor@gmail.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

authored by

Yauhen Kharuzhy and committed by
Andy Shevchenko
d740795d c656829f

+265 -72
+8 -2
drivers/platform/x86/Kconfig
··· 927 927 This driver add support for the INT33FE ACPI device found on 928 928 some Intel Cherry Trail devices. 929 929 930 + There are two kinds of INT33FE ACPI device possible: for hardware 931 + with USB Type-C and Micro-B connectors. This driver supports both. 932 + 930 933 The INT33FE ACPI device has a CRS table with I2cSerialBusV2 931 - resources for 3 devices: Maxim MAX17047 Fuel Gauge Controller, 934 + resources for Fuel Gauge Controller and (in the Type-C variant) 932 935 FUSB302 USB Type-C Controller and PI3USB30532 USB switch. 933 936 This driver instantiates i2c-clients for these, so that standard 934 937 i2c drivers for these chips can bind to the them. 935 938 936 939 If you enable this driver it is advised to also select 937 - CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m. 940 + CONFIG_BATTERY_BQ27XXX=m or CONFIG_BATTERY_BQ27XXX_I2C=m for Micro-B 941 + device and CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m 942 + for Type-C device. 943 + 938 944 939 945 config INTEL_INT0002_VGPIO 940 946 tristate "Intel ACPI INT0002 Virtual GPIO driver"
+4
drivers/platform/x86/Makefile
··· 61 61 obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o 62 62 obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o 63 63 obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o 64 + intel_cht_int33fe-objs := intel_cht_int33fe_common.o \ 65 + intel_cht_int33fe_typec.o \ 66 + intel_cht_int33fe_microb.o 67 + 64 68 obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o 65 69 obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o 66 70 obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
+8 -70
drivers/platform/x86/intel_cht_int33fe.c drivers/platform/x86/intel_cht_int33fe_typec.c
··· 17 17 * for these chips can bind to the them. 18 18 */ 19 19 20 - #include <linux/acpi.h> 21 20 #include <linux/i2c.h> 22 21 #include <linux/interrupt.h> 23 - #include <linux/module.h> 24 22 #include <linux/pci.h> 25 23 #include <linux/platform_device.h> 26 24 #include <linux/regulator/consumer.h> 27 25 #include <linux/slab.h> 28 26 #include <linux/usb/pd.h> 29 27 30 - #define EXPECTED_PTYPE 4 28 + #include "intel_cht_int33fe_common.h" 31 29 32 30 enum { 33 31 INT33FE_NODE_FUSB302, ··· 34 36 INT33FE_NODE_DISPLAYPORT, 35 37 INT33FE_NODE_USB_CONNECTOR, 36 38 INT33FE_NODE_MAX, 37 - }; 38 - 39 - struct cht_int33fe_data { 40 - struct i2c_client *max17047; 41 - struct i2c_client *fusb302; 42 - struct i2c_client *pi3usb30532; 43 - 44 - struct fwnode_handle *dp; 45 39 }; 46 40 47 41 static const struct software_node nodes[]; ··· 241 251 strlcpy(board_info.type, "max17047", I2C_NAME_SIZE); 242 252 board_info.dev_name = "max17047"; 243 253 board_info.fwnode = fwnode; 244 - data->max17047 = i2c_acpi_new_device(dev, 1, &board_info); 254 + data->battery_fg = i2c_acpi_new_device(dev, 1, &board_info); 245 255 246 - return PTR_ERR_OR_ZERO(data->max17047); 256 + return PTR_ERR_OR_ZERO(data->battery_fg); 247 257 } 248 258 249 - static int cht_int33fe_probe(struct platform_device *pdev) 259 + int cht_int33fe_typec_probe(struct cht_int33fe_data *data) 250 260 { 251 - struct device *dev = &pdev->dev; 261 + struct device *dev = data->dev; 252 262 struct i2c_board_info board_info; 253 - struct cht_int33fe_data *data; 254 263 struct fwnode_handle *fwnode; 255 264 struct regulator *regulator; 256 - unsigned long long ptyp; 257 - acpi_status status; 258 265 int fusb302_irq; 259 266 int ret; 260 - 261 - status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp); 262 - if (ACPI_FAILURE(status)) { 263 - dev_err(dev, "Error getting PTYPE\n"); 264 - return -ENODEV; 265 - } 266 - 267 - /* 268 - * The same ACPI HID is used for different configurations check PTYP 269 - * to ensure that we are dealing with the expected config. 270 - */ 271 - if (ptyp != EXPECTED_PTYPE) 272 - return -ENODEV; 273 - 274 - /* Check presence of INT34D3 (hardware-rev 3) expected for ptype == 4 */ 275 - if (!acpi_dev_present("INT34D3", "1", 3)) { 276 - dev_err(dev, "Error PTYPE == %d, but no INT34D3 device\n", 277 - EXPECTED_PTYPE); 278 - return -ENODEV; 279 - } 280 267 281 268 /* 282 269 * We expect the WC PMIC to be paired with a TI bq24292i charger-IC. ··· 283 316 dev_err(dev, "Error getting FUSB302 irq\n"); 284 317 return fusb302_irq; 285 318 } 286 - 287 - data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 288 - if (!data) 289 - return -ENOMEM; 290 319 291 320 ret = cht_int33fe_add_nodes(data); 292 321 if (ret) ··· 328 365 goto out_unregister_fusb302; 329 366 } 330 367 331 - platform_set_drvdata(pdev, data); 332 - 333 368 return 0; 334 369 335 370 out_unregister_fusb302: 336 371 i2c_unregister_device(data->fusb302); 337 372 338 373 out_unregister_max17047: 339 - i2c_unregister_device(data->max17047); 374 + i2c_unregister_device(data->battery_fg); 340 375 341 376 out_remove_nodes: 342 377 cht_int33fe_remove_nodes(data); ··· 342 381 return ret; 343 382 } 344 383 345 - static int cht_int33fe_remove(struct platform_device *pdev) 384 + int cht_int33fe_typec_remove(struct cht_int33fe_data *data) 346 385 { 347 - struct cht_int33fe_data *data = platform_get_drvdata(pdev); 348 - 349 386 i2c_unregister_device(data->pi3usb30532); 350 387 i2c_unregister_device(data->fusb302); 351 - i2c_unregister_device(data->max17047); 388 + i2c_unregister_device(data->battery_fg); 352 389 353 390 cht_int33fe_remove_nodes(data); 354 391 355 392 return 0; 356 393 } 357 - 358 - static const struct acpi_device_id cht_int33fe_acpi_ids[] = { 359 - { "INT33FE", }, 360 - { } 361 - }; 362 - MODULE_DEVICE_TABLE(acpi, cht_int33fe_acpi_ids); 363 - 364 - static struct platform_driver cht_int33fe_driver = { 365 - .driver = { 366 - .name = "Intel Cherry Trail ACPI INT33FE driver", 367 - .acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids), 368 - }, 369 - .probe = cht_int33fe_probe, 370 - .remove = cht_int33fe_remove, 371 - }; 372 - 373 - module_platform_driver(cht_int33fe_driver); 374 - 375 - MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE pseudo device driver"); 376 - MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 377 - MODULE_LICENSE("GPL v2");
+147
drivers/platform/x86/intel_cht_int33fe_common.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Common code for Intel Cherry Trail ACPI INT33FE pseudo device drivers 4 + * (USB Micro-B and Type-C connector variants). 5 + * 6 + * Copyright (c) 2019 Yauhen Kharuzhy <jekhor@gmail.com> 7 + */ 8 + 9 + #include <linux/acpi.h> 10 + #include <linux/i2c.h> 11 + #include <linux/module.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/slab.h> 14 + 15 + #include "intel_cht_int33fe_common.h" 16 + 17 + #define EXPECTED_PTYPE 4 18 + 19 + static int cht_int33fe_i2c_res_filter(struct acpi_resource *ares, void *data) 20 + { 21 + struct acpi_resource_i2c_serialbus *sb; 22 + int *count = data; 23 + 24 + if (i2c_acpi_get_i2c_resource(ares, &sb)) 25 + (*count)++; 26 + 27 + return 1; 28 + } 29 + 30 + static int cht_int33fe_count_i2c_clients(struct device *dev) 31 + { 32 + struct acpi_device *adev; 33 + LIST_HEAD(resource_list); 34 + int count = 0; 35 + 36 + adev = ACPI_COMPANION(dev); 37 + if (!adev) 38 + return -EINVAL; 39 + 40 + acpi_dev_get_resources(adev, &resource_list, 41 + cht_int33fe_i2c_res_filter, &count); 42 + 43 + acpi_dev_free_resource_list(&resource_list); 44 + 45 + return count; 46 + } 47 + 48 + static int cht_int33fe_check_hw_type(struct device *dev) 49 + { 50 + unsigned long long ptyp; 51 + acpi_status status; 52 + int ret; 53 + 54 + status = acpi_evaluate_integer(ACPI_HANDLE(dev), "PTYP", NULL, &ptyp); 55 + if (ACPI_FAILURE(status)) { 56 + dev_err(dev, "Error getting PTYPE\n"); 57 + return -ENODEV; 58 + } 59 + 60 + /* 61 + * The same ACPI HID is used for different configurations check PTYP 62 + * to ensure that we are dealing with the expected config. 63 + */ 64 + if (ptyp != EXPECTED_PTYPE) 65 + return -ENODEV; 66 + 67 + /* Check presence of INT34D3 (hardware-rev 3) expected for ptype == 4 */ 68 + if (!acpi_dev_present("INT34D3", "1", 3)) { 69 + dev_err(dev, "Error PTYPE == %d, but no INT34D3 device\n", 70 + EXPECTED_PTYPE); 71 + return -ENODEV; 72 + } 73 + 74 + ret = cht_int33fe_count_i2c_clients(dev); 75 + if (ret < 0) 76 + return ret; 77 + 78 + switch (ret) { 79 + case 2: 80 + return INT33FE_HW_MICROB; 81 + case 4: 82 + return INT33FE_HW_TYPEC; 83 + default: 84 + return -ENODEV; 85 + } 86 + } 87 + 88 + static int cht_int33fe_probe(struct platform_device *pdev) 89 + { 90 + struct cht_int33fe_data *data; 91 + struct device *dev = &pdev->dev; 92 + int ret; 93 + 94 + ret = cht_int33fe_check_hw_type(dev); 95 + if (ret < 0) 96 + return ret; 97 + 98 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 99 + if (!data) 100 + return -ENOMEM; 101 + 102 + data->dev = dev; 103 + 104 + switch (ret) { 105 + case INT33FE_HW_MICROB: 106 + data->probe = cht_int33fe_microb_probe; 107 + data->remove = cht_int33fe_microb_remove; 108 + break; 109 + 110 + case INT33FE_HW_TYPEC: 111 + data->probe = cht_int33fe_typec_probe; 112 + data->remove = cht_int33fe_typec_remove; 113 + break; 114 + } 115 + 116 + platform_set_drvdata(pdev, data); 117 + 118 + return data->probe(data); 119 + } 120 + 121 + static int cht_int33fe_remove(struct platform_device *pdev) 122 + { 123 + struct cht_int33fe_data *data = platform_get_drvdata(pdev); 124 + 125 + return data->remove(data); 126 + } 127 + 128 + static const struct acpi_device_id cht_int33fe_acpi_ids[] = { 129 + { "INT33FE", }, 130 + { } 131 + }; 132 + MODULE_DEVICE_TABLE(acpi, cht_int33fe_acpi_ids); 133 + 134 + static struct platform_driver cht_int33fe_driver = { 135 + .driver = { 136 + .name = "Intel Cherry Trail ACPI INT33FE driver", 137 + .acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids), 138 + }, 139 + .probe = cht_int33fe_probe, 140 + .remove = cht_int33fe_remove, 141 + }; 142 + 143 + module_platform_driver(cht_int33fe_driver); 144 + 145 + MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE pseudo device driver"); 146 + MODULE_AUTHOR("Yauhen Kharuzhy <jekhor@gmail.com>"); 147 + MODULE_LICENSE("GPL v2");
+41
drivers/platform/x86/intel_cht_int33fe_common.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Common code for Intel Cherry Trail ACPI INT33FE pseudo device drivers 4 + * (USB Micro-B and Type-C connector variants), header file 5 + * 6 + * Copyright (c) 2019 Yauhen Kharuzhy <jekhor@gmail.com> 7 + */ 8 + 9 + #ifndef _INTEL_CHT_INT33FE_COMMON_H 10 + #define _INTEL_CHT_INT33FE_COMMON_H 11 + 12 + #include <linux/device.h> 13 + #include <linux/fwnode.h> 14 + #include <linux/i2c.h> 15 + 16 + enum int33fe_hw_type { 17 + INT33FE_HW_MICROB, 18 + INT33FE_HW_TYPEC, 19 + }; 20 + 21 + struct cht_int33fe_data { 22 + struct device *dev; 23 + 24 + int (*probe)(struct cht_int33fe_data *data); 25 + int (*remove)(struct cht_int33fe_data *data); 26 + 27 + struct i2c_client *battery_fg; 28 + 29 + /* Type-C only */ 30 + struct i2c_client *fusb302; 31 + struct i2c_client *pi3usb30532; 32 + 33 + struct fwnode_handle *dp; 34 + }; 35 + 36 + int cht_int33fe_microb_probe(struct cht_int33fe_data *data); 37 + int cht_int33fe_microb_remove(struct cht_int33fe_data *data); 38 + int cht_int33fe_typec_probe(struct cht_int33fe_data *data); 39 + int cht_int33fe_typec_remove(struct cht_int33fe_data *data); 40 + 41 + #endif /* _INTEL_CHT_INT33FE_COMMON_H */
+57
drivers/platform/x86/intel_cht_int33fe_microb.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Intel Cherry Trail ACPI INT33FE pseudo device driver for devices with 4 + * USB Micro-B connector (e.g. without of FUSB302 USB Type-C controller) 5 + * 6 + * Copyright (C) 2019 Yauhen Kharuzhy <jekhor@gmail.com> 7 + * 8 + * At least one Intel Cherry Trail based device which ship with Windows 10 9 + * (Lenovo YogaBook YB1-X91L/F tablet), have this weird INT33FE ACPI device 10 + * with a CRS table with 2 I2cSerialBusV2 resources, for 2 different chips 11 + * attached to various i2c busses: 12 + * 1. The Whiskey Cove PMIC, which is also described by the INT34D3 ACPI device 13 + * 2. TI BQ27542 Fuel Gauge Controller 14 + * 15 + * So this driver is a stub / pseudo driver whose only purpose is to 16 + * instantiate i2c-client for battery fuel gauge, so that standard i2c driver 17 + * for these chip can bind to the it. 18 + */ 19 + 20 + #include <linux/acpi.h> 21 + #include <linux/i2c.h> 22 + #include <linux/module.h> 23 + #include <linux/pci.h> 24 + #include <linux/platform_device.h> 25 + #include <linux/regulator/consumer.h> 26 + #include <linux/slab.h> 27 + #include <linux/usb/pd.h> 28 + 29 + #include "intel_cht_int33fe_common.h" 30 + 31 + static const char * const bq27xxx_suppliers[] = { "bq25890-charger" }; 32 + 33 + static const struct property_entry bq27xxx_props[] = { 34 + PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq27xxx_suppliers), 35 + { } 36 + }; 37 + 38 + int cht_int33fe_microb_probe(struct cht_int33fe_data *data) 39 + { 40 + struct device *dev = data->dev; 41 + struct i2c_board_info board_info; 42 + 43 + memset(&board_info, 0, sizeof(board_info)); 44 + strscpy(board_info.type, "bq27542", ARRAY_SIZE(board_info.type)); 45 + board_info.dev_name = "bq27542"; 46 + board_info.properties = bq27xxx_props; 47 + data->battery_fg = i2c_acpi_new_device(dev, 1, &board_info); 48 + 49 + return PTR_ERR_OR_ZERO(data->battery_fg); 50 + } 51 + 52 + int cht_int33fe_microb_remove(struct cht_int33fe_data *data) 53 + { 54 + i2c_unregister_device(data->battery_fg); 55 + 56 + return 0; 57 + }