1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intel Cherry Trail ACPI INT33FE pseudo device driver 4 * 5 * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> 6 * 7 * Some Intel Cherry Trail based device which ship with Windows 10, have 8 * this weird INT33FE ACPI device with a CRS table with 4 I2cSerialBusV2 9 * resources, for 4 different chips attached to various I²C buses: 10 * 1. The Whiskey Cove PMIC, which is also described by the INT34D3 ACPI device 11 * 2. Maxim MAX17047 Fuel Gauge Controller 12 * 3. FUSB302 USB Type-C Controller 13 * 4. PI3USB30532 USB switch 14 * 15 * So this driver is a stub / pseudo driver whose only purpose is to 16 * instantiate I²C clients for chips 2 - 4, so that standard I²C drivers 17 * for these chips can bind to the them. 18 */ 19 20 #include <linux/dmi.h> 21 #include <linux/i2c.h> 22 #include <linux/interrupt.h> 23 #include <linux/pci.h> 24 #include <linux/platform_device.h> 25 #include <linux/property.h> 26 #include <linux/regulator/consumer.h> 27 #include <linux/slab.h> 28 #include <linux/usb/pd.h> 29 30 struct cht_int33fe_data { 31 struct i2c_client *battery_fg; 32 struct i2c_client *fusb302; 33 struct i2c_client *pi3usb30532; 34 struct fwnode_handle *dp; 35 }; 36 37 /* 38 * Grrr, I severely dislike buggy BIOS-es. At least one BIOS enumerates 39 * the max17047 both through the INT33FE ACPI device (it is right there 40 * in the resources table) as well as through a separate MAX17047 device. 41 * 42 * These helpers are used to work around this by checking if an I²C client 43 * for the max17047 has already been registered. 44 */ 45 static int cht_int33fe_check_for_max17047(struct device *dev, void *data) 46 { 47 struct i2c_client **max17047 = data; 48 struct acpi_device *adev; 49 50 adev = ACPI_COMPANION(dev); 51 if (!adev) 52 return 0; 53 54 /* The MAX17047 ACPI node doesn't have an UID, so we don't check that */ 55 if (!acpi_dev_hid_uid_match(adev, "MAX17047", NULL)) 56 return 0; 57 58 *max17047 = to_i2c_client(dev); 59 return 1; 60 } 61 62 static const char * const max17047_suppliers[] = { "bq24190-charger" }; 63 64 static const struct property_entry max17047_properties[] = { 65 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", max17047_suppliers), 66 { } 67 }; 68 69 static const struct software_node max17047_node = { 70 .name = "max17047", 71 .properties = max17047_properties, 72 }; 73 74 /* 75 * We are not using inline property here because those are constant, 76 * and we need to adjust this one at runtime to point to real 77 * software node. 78 */ 79 static struct software_node_ref_args fusb302_mux_refs[] = { 80 { .node = NULL }, 81 }; 82 83 static const struct property_entry fusb302_properties[] = { 84 PROPERTY_ENTRY_STRING("linux,extcon-name", "cht_wcove_pwrsrc"), 85 PROPERTY_ENTRY_REF_ARRAY("usb-role-switch", fusb302_mux_refs), 86 { } 87 }; 88 89 static const struct software_node fusb302_node = { 90 .name = "fusb302", 91 .properties = fusb302_properties, 92 }; 93 94 #define PDO_FIXED_FLAGS \ 95 (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM) 96 97 static const u32 src_pdo[] = { 98 PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), 99 }; 100 101 static const u32 snk_pdo[] = { 102 PDO_FIXED(5000, 400, PDO_FIXED_FLAGS), 103 PDO_VAR(5000, 12000, 3000), 104 }; 105 106 static const struct software_node pi3usb30532_node = { 107 .name = "pi3usb30532", 108 }; 109 110 static const struct software_node displayport_node = { 111 .name = "displayport", 112 }; 113 114 static const struct property_entry usb_connector_properties[] = { 115 PROPERTY_ENTRY_STRING("data-role", "dual"), 116 PROPERTY_ENTRY_STRING("power-role", "dual"), 117 PROPERTY_ENTRY_STRING("try-power-role", "sink"), 118 PROPERTY_ENTRY_U32_ARRAY("source-pdos", src_pdo), 119 PROPERTY_ENTRY_U32_ARRAY("sink-pdos", snk_pdo), 120 PROPERTY_ENTRY_U32("op-sink-microwatt", 2500000), 121 PROPERTY_ENTRY_REF("orientation-switch", &pi3usb30532_node), 122 PROPERTY_ENTRY_REF("mode-switch", &pi3usb30532_node), 123 PROPERTY_ENTRY_REF("displayport", &displayport_node), 124 { } 125 }; 126 127 static const struct software_node usb_connector_node = { 128 .name = "connector", 129 .parent = &fusb302_node, 130 .properties = usb_connector_properties, 131 }; 132 133 static const struct software_node altmodes_node = { 134 .name = "altmodes", 135 .parent = &usb_connector_node, 136 }; 137 138 static const struct property_entry dp_altmode_properties[] = { 139 PROPERTY_ENTRY_U16("svid", 0xff01), 140 PROPERTY_ENTRY_U32("vdo", 0x0c0086), 141 { } 142 }; 143 144 static const struct software_node dp_altmode_node = { 145 .name = "displayport-altmode", 146 .parent = &altmodes_node, 147 .properties = dp_altmode_properties, 148 }; 149 150 static const struct software_node *node_group[] = { 151 &fusb302_node, 152 &max17047_node, 153 &pi3usb30532_node, 154 &displayport_node, 155 &usb_connector_node, 156 &altmodes_node, 157 &dp_altmode_node, 158 NULL 159 }; 160 161 static int cht_int33fe_setup_dp(struct cht_int33fe_data *data) 162 { 163 struct fwnode_handle *fwnode; 164 struct pci_dev *pdev; 165 166 fwnode = software_node_fwnode(&displayport_node); 167 if (!fwnode) 168 return -ENODEV; 169 170 /* First let's find the GPU PCI device */ 171 pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); 172 if (!pdev || pdev->vendor != PCI_VENDOR_ID_INTEL) { 173 pci_dev_put(pdev); 174 return -ENODEV; 175 } 176 177 /* Then the DP-2 child device node */ 178 data->dp = device_get_named_child_node(&pdev->dev, "DD04"); 179 pci_dev_put(pdev); 180 if (!data->dp) 181 return -ENODEV; 182 183 fwnode->secondary = ERR_PTR(-ENODEV); 184 data->dp->secondary = fwnode; 185 186 return 0; 187 } 188 189 static void cht_int33fe_remove_nodes(struct cht_int33fe_data *data) 190 { 191 software_node_unregister_node_group(node_group); 192 193 if (fusb302_mux_refs[0].node) { 194 fwnode_handle_put(software_node_fwnode(fusb302_mux_refs[0].node)); 195 fusb302_mux_refs[0].node = NULL; 196 } 197 198 if (data->dp) { 199 data->dp->secondary = NULL; 200 fwnode_handle_put(data->dp); 201 data->dp = NULL; 202 } 203 } 204 205 static int cht_int33fe_add_nodes(struct cht_int33fe_data *data) 206 { 207 const struct software_node *mux_ref_node; 208 int ret; 209 210 /* 211 * There is no ACPI device node for the USB role mux, so we need to wait 212 * until the mux driver has created software node for the mux device. 213 * It means we depend on the mux driver. This function will return 214 * -EPROBE_DEFER until the mux device is registered. 215 */ 216 mux_ref_node = software_node_find_by_name(NULL, "intel-xhci-usb-sw"); 217 if (!mux_ref_node) 218 return -EPROBE_DEFER; 219 220 /* 221 * Update node used in "usb-role-switch" property. Note that we 222 * rely on software_node_register_node_group() to use the original 223 * instance of properties instead of copying them. 224 */ 225 fusb302_mux_refs[0].node = mux_ref_node; 226 227 ret = software_node_register_node_group(node_group); 228 if (ret) 229 return ret; 230 231 /* The devices that are not created in this driver need extra steps. */ 232 233 /* 234 * The DP connector does have ACPI device node. In this case we can just 235 * find that ACPI node and assign our node as the secondary node to it. 236 */ 237 ret = cht_int33fe_setup_dp(data); 238 if (ret) 239 goto err_remove_nodes; 240 241 return 0; 242 243 err_remove_nodes: 244 cht_int33fe_remove_nodes(data); 245 246 return ret; 247 } 248 249 static int 250 cht_int33fe_register_max17047(struct device *dev, struct cht_int33fe_data *data) 251 { 252 struct i2c_client *max17047 = NULL; 253 struct i2c_board_info board_info; 254 struct fwnode_handle *fwnode; 255 int ret; 256 257 fwnode = software_node_fwnode(&max17047_node); 258 if (!fwnode) 259 return -ENODEV; 260 261 i2c_for_each_dev(&max17047, cht_int33fe_check_for_max17047); 262 if (max17047) { 263 /* Pre-existing I²C client for the max17047, add device properties */ 264 set_secondary_fwnode(&max17047->dev, fwnode); 265 /* And re-probe to get the new device properties applied */ 266 ret = device_reprobe(&max17047->dev); 267 if (ret) 268 dev_warn(dev, "Reprobing max17047 error: %d\n", ret); 269 return 0; 270 } 271 272 memset(&board_info, 0, sizeof(board_info)); 273 strscpy(board_info.type, "max17047", I2C_NAME_SIZE); 274 board_info.dev_name = "max17047"; 275 board_info.fwnode = fwnode; 276 data->battery_fg = i2c_acpi_new_device(dev, 1, &board_info); 277 278 return PTR_ERR_OR_ZERO(data->battery_fg); 279 } 280 281 static const struct dmi_system_id cht_int33fe_typec_ids[] = { 282 { 283 /* 284 * GPD win / GPD pocket mini laptops 285 * 286 * This DMI match may not seem unique, but it is. In the 67000+ 287 * DMI decode dumps from linux-hardware.org only 116 have 288 * board_vendor set to "AMI Corporation" and of those 116 only 289 * the GPD win's and pocket's board_name is "Default string". 290 */ 291 .matches = { 292 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), 293 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), 294 DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"), 295 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), 296 }, 297 }, 298 { } 299 }; 300 MODULE_DEVICE_TABLE(dmi, cht_int33fe_typec_ids); 301 302 static int cht_int33fe_typec_probe(struct platform_device *pdev) 303 { 304 struct i2c_board_info board_info; 305 struct device *dev = &pdev->dev; 306 struct cht_int33fe_data *data; 307 struct fwnode_handle *fwnode; 308 struct regulator *regulator; 309 int fusb302_irq; 310 int ret; 311 312 if (!dmi_check_system(cht_int33fe_typec_ids)) 313 return -ENODEV; 314 315 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 316 if (!data) 317 return -ENOMEM; 318 319 /* 320 * We expect the WC PMIC to be paired with a TI bq24292i charger-IC. 321 * We check for the bq24292i vbus regulator here, this has 2 purposes: 322 * 1) The bq24292i allows charging with up to 12V, setting the fusb302's 323 * max-snk voltage to 12V with another charger-IC is not good. 324 * 2) For the fusb302 driver to get the bq24292i vbus regulator, the 325 * regulator-map, which is part of the bq24292i regulator_init_data, 326 * must be registered before the fusb302 is instantiated, otherwise 327 * it will end up with a dummy-regulator. 328 * Note "cht_wc_usb_typec_vbus" comes from the regulator_init_data 329 * which is defined in i2c-cht-wc.c from where the bq24292i I²C client 330 * gets instantiated. We use regulator_get_optional here so that we 331 * don't end up getting a dummy-regulator ourselves. 332 */ 333 regulator = regulator_get_optional(dev, "cht_wc_usb_typec_vbus"); 334 if (IS_ERR(regulator)) { 335 ret = PTR_ERR(regulator); 336 return (ret == -ENODEV) ? -EPROBE_DEFER : ret; 337 } 338 regulator_put(regulator); 339 340 /* The FUSB302 uses the IRQ at index 1 and is the only IRQ user */ 341 fusb302_irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 1); 342 if (fusb302_irq < 0) { 343 if (fusb302_irq != -EPROBE_DEFER) 344 dev_err(dev, "Error getting FUSB302 irq\n"); 345 return fusb302_irq; 346 } 347 348 ret = cht_int33fe_add_nodes(data); 349 if (ret) 350 return ret; 351 352 /* Work around BIOS bug, see comment on cht_int33fe_check_for_max17047() */ 353 ret = cht_int33fe_register_max17047(dev, data); 354 if (ret) 355 goto out_remove_nodes; 356 357 fwnode = software_node_fwnode(&fusb302_node); 358 if (!fwnode) { 359 ret = -ENODEV; 360 goto out_unregister_max17047; 361 } 362 363 memset(&board_info, 0, sizeof(board_info)); 364 strscpy(board_info.type, "typec_fusb302", I2C_NAME_SIZE); 365 board_info.dev_name = "fusb302"; 366 board_info.fwnode = fwnode; 367 board_info.irq = fusb302_irq; 368 369 data->fusb302 = i2c_acpi_new_device(dev, 2, &board_info); 370 if (IS_ERR(data->fusb302)) { 371 ret = PTR_ERR(data->fusb302); 372 goto out_unregister_max17047; 373 } 374 375 fwnode = software_node_fwnode(&pi3usb30532_node); 376 if (!fwnode) { 377 ret = -ENODEV; 378 goto out_unregister_fusb302; 379 } 380 381 memset(&board_info, 0, sizeof(board_info)); 382 board_info.dev_name = "pi3usb30532"; 383 board_info.fwnode = fwnode; 384 strscpy(board_info.type, "pi3usb30532", I2C_NAME_SIZE); 385 386 data->pi3usb30532 = i2c_acpi_new_device(dev, 3, &board_info); 387 if (IS_ERR(data->pi3usb30532)) { 388 ret = PTR_ERR(data->pi3usb30532); 389 goto out_unregister_fusb302; 390 } 391 392 platform_set_drvdata(pdev, data); 393 394 return 0; 395 396 out_unregister_fusb302: 397 i2c_unregister_device(data->fusb302); 398 399 out_unregister_max17047: 400 i2c_unregister_device(data->battery_fg); 401 402 out_remove_nodes: 403 cht_int33fe_remove_nodes(data); 404 405 return ret; 406 } 407 408 static void cht_int33fe_typec_remove(struct platform_device *pdev) 409 { 410 struct cht_int33fe_data *data = platform_get_drvdata(pdev); 411 412 i2c_unregister_device(data->pi3usb30532); 413 i2c_unregister_device(data->fusb302); 414 i2c_unregister_device(data->battery_fg); 415 416 cht_int33fe_remove_nodes(data); 417 } 418 419 static const struct acpi_device_id cht_int33fe_acpi_ids[] = { 420 { "INT33FE", }, 421 { } 422 }; 423 424 static struct platform_driver cht_int33fe_typec_driver = { 425 .driver = { 426 .name = "Intel Cherry Trail ACPI INT33FE Type-C driver", 427 .acpi_match_table = ACPI_PTR(cht_int33fe_acpi_ids), 428 }, 429 .probe = cht_int33fe_typec_probe, 430 .remove_new = cht_int33fe_typec_remove, 431 }; 432 433 module_platform_driver(cht_int33fe_typec_driver); 434 435 MODULE_DESCRIPTION("Intel Cherry Trail ACPI INT33FE Type-C pseudo device driver"); 436 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 437 MODULE_LICENSE("GPL v2"); 438