diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c
index d6d2bc6f3aaf0..e5015dfaa81ec 100644
--- a/drivers/platform/chrome/chromeos_laptop.c
+++ b/drivers/platform/chrome/chromeos_laptop.c
@@ -12,6 +12,7 @@
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/platform_device.h>
 
 #define ATMEL_TP_I2C_ADDR	0x4b
@@ -23,14 +24,11 @@
 #define ISL_ALS_I2C_ADDR	0x44
 #define TAOS_ALS_I2C_ADDR	0x29
 
-#define MAX_I2C_DEVICE_DEFERRALS	5
-
 static const char *i2c_adapter_names[] = {
 	"SMBus I801 adapter",
 	"i915 gmbus vga",
 	"i915 gmbus panel",
 	"Synopsys DesignWare I2C adapter",
-	"Synopsys DesignWare I2C adapter",
 };
 
 /* Keep this enum consistent with i2c_adapter_names */
@@ -38,15 +36,7 @@ enum i2c_adapter_type {
 	I2C_ADAPTER_SMBUS = 0,
 	I2C_ADAPTER_VGADDC,
 	I2C_ADAPTER_PANEL,
-	I2C_ADAPTER_DESIGNWARE_0,
-	I2C_ADAPTER_DESIGNWARE_1,
-};
-
-enum i2c_peripheral_state {
-	UNPROBED = 0,
-	PROBED,
-	TIMEDOUT,
-	FAILED,
+	I2C_ADAPTER_DESIGNWARE,
 };
 
 struct i2c_peripheral {
@@ -54,10 +44,9 @@ struct i2c_peripheral {
 	unsigned short alt_addr;
 	const char *dmi_name;
 	enum i2c_adapter_type type;
+	u32 pci_devid;
 
-	enum i2c_peripheral_state state;
 	struct i2c_client *client;
-	int tries;
 };
 
 #define MAX_I2C_PERIPHERALS 4
@@ -69,19 +58,12 @@ struct chromeos_laptop {
 static struct chromeos_laptop *cros_laptop;
 
 static struct i2c_client *
-chromes_laptop_instantiate_i2c_device(int bus,
+chromes_laptop_instantiate_i2c_device(struct i2c_adapter *adapter,
 				      struct i2c_board_info *info,
 				      unsigned short alt_addr)
 {
-	struct i2c_adapter *adapter;
-	struct i2c_client *client = NULL;
 	const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
-
-	adapter = i2c_get_adapter(bus);
-	if (!adapter) {
-		pr_err("failed to get i2c adapter %d\n", bus);
-		return NULL;
-	}
+	struct i2c_client *client;
 
 	/*
 	 * Add the i2c device. If we can't detect it at the primary
@@ -102,126 +84,103 @@ chromes_laptop_instantiate_i2c_device(int bus,
 					      alt_addr_list, NULL);
 		if (dummy) {
 			pr_debug("%d-%02x is probed at %02x\n",
-				 bus, info->addr, dummy->addr);
+				 adapter->nr, info->addr, dummy->addr);
 			i2c_unregister_device(dummy);
 			client = i2c_new_device(adapter, info);
 		}
 	}
 
 	if (!client)
-		pr_notice("failed to register device %d-%02x\n",
-			  bus, info->addr);
+		pr_debug("failed to register device %d-%02x\n",
+			 adapter->nr, info->addr);
 	else
-		pr_debug("added i2c device %d-%02x\n", bus, info->addr);
+		pr_debug("added i2c device %d-%02x\n",
+			 adapter->nr, info->addr);
 
-	i2c_put_adapter(adapter);
 	return client;
 }
 
-struct i2c_lookup {
-	const char *name;
-	int instance;
-	int n;
-};
-
-static int __find_i2c_adap(struct device *dev, void *data)
+static bool chromeos_laptop_match_adapter_devid(struct device *dev, u32 devid)
 {
-	struct i2c_lookup *lookup = data;
-	static const char *prefix = "i2c-";
-	struct i2c_adapter *adapter;
+	struct pci_dev *pdev;
 
-	if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0)
-		return 0;
-	adapter = to_i2c_adapter(dev);
-	if (strncmp(adapter->name, lookup->name, strlen(lookup->name)) == 0 &&
-	    lookup->n++ == lookup->instance)
-		return 1;
-	return 0;
-}
+	if (!dev_is_pci(dev))
+		return false;
 
-static int find_i2c_adapter_num(enum i2c_adapter_type type)
-{
-	struct device *dev = NULL;
-	struct i2c_adapter *adapter;
-	struct i2c_lookup lookup;
-
-	memset(&lookup, 0, sizeof(lookup));
-	lookup.name = i2c_adapter_names[type];
-	lookup.instance = (type == I2C_ADAPTER_DESIGNWARE_1) ? 1 : 0;
-
-	/* find the adapter by name */
-	dev = bus_find_device(&i2c_bus_type, NULL, &lookup, __find_i2c_adap);
-	if (!dev) {
-		/* Adapters may appear later. Deferred probing will retry */
-		pr_notice("i2c adapter %s not found on system.\n",
-			  lookup.name);
-		return -ENODEV;
-	}
-	adapter = to_i2c_adapter(dev);
-	return adapter->nr;
+	pdev = to_pci_dev(dev);
+	return devid == PCI_DEVID(pdev->bus->number, pdev->devfn);
 }
 
-static int chromeos_laptop_add_peripheral(struct i2c_peripheral *i2c_dev)
+static void chromeos_laptop_check_adapter(struct i2c_adapter *adapter)
 {
-	struct i2c_client *client;
-	int bus;
+	struct i2c_peripheral *i2c_dev;
+	int i;
 
-	/*
-	 * Check that the i2c adapter is present.
-	 * -EPROBE_DEFER if missing as the adapter may appear much
-	 * later.
-	 */
-	bus = find_i2c_adapter_num(i2c_dev->type);
-	if (bus < 0)
-		return bus == -ENODEV ? -EPROBE_DEFER : bus;
-
-	client = chromes_laptop_instantiate_i2c_device(bus,
-						       &i2c_dev->board_info,
-						       i2c_dev->alt_addr);
-	if (!client) {
-		/*
-		 * Set -EPROBE_DEFER a limited num of times
-		 * if device is not successfully added.
-		 */
-		if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) {
-			return -EPROBE_DEFER;
-		} else {
-			/* Ran out of tries. */
-			pr_notice("ran out of tries for device.\n");
-			i2c_dev->state = TIMEDOUT;
-			return -EIO;
-		}
-	}
+	for (i = 0; i < MAX_I2C_PERIPHERALS; i++) {
+		i2c_dev = &cros_laptop->i2c_peripherals[i];
 
-	i2c_dev->client = client;
-	i2c_dev->state = PROBED;
+		/* No more peripherals */
+		if (!i2c_dev->board_info.addr)
+			break;
 
-	return 0;
+		/* Skip devices already created */
+		if (i2c_dev->client)
+			continue;
+
+		if (strncmp(adapter->name, i2c_adapter_names[i2c_dev->type],
+			    strlen(i2c_adapter_names[i2c_dev->type])))
+			continue;
+
+		if (i2c_dev->pci_devid &&
+		    !chromeos_laptop_match_adapter_devid(adapter->dev.parent,
+							 i2c_dev->pci_devid)) {
+			continue;
+		}
+
+		i2c_dev->client =
+			chromes_laptop_instantiate_i2c_device(adapter,
+							&i2c_dev->board_info,
+							i2c_dev->alt_addr);
+	}
 }
 
-static int chromeos_laptop_probe(struct platform_device *pdev)
+static void chromeos_laptop_detach_i2c_client(struct i2c_client *client)
 {
 	struct i2c_peripheral *i2c_dev;
 	int i;
-	int ret = 0;
 
 	for (i = 0; i < MAX_I2C_PERIPHERALS; i++) {
 		i2c_dev = &cros_laptop->i2c_peripherals[i];
 
-		/* No more peripherals. */
-		if (!i2c_dev->board_info.addr)
-			break;
-
-		if (i2c_dev->state != UNPROBED)
-			continue;
+		if (i2c_dev->client == client)
+			i2c_dev->client = NULL;
+	}
+}
 
-		if (chromeos_laptop_add_peripheral(i2c_dev) == -EPROBE_DEFER)
-			ret = -EPROBE_DEFER;
+static int chromeos_laptop_i2c_notifier_call(struct notifier_block *nb,
+					     unsigned long action, void *data)
+{
+	struct device *dev = data;
+
+	switch (action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		if (dev->type == &i2c_adapter_type)
+			chromeos_laptop_check_adapter(to_i2c_adapter(dev));
+		break;
+
+	case BUS_NOTIFY_REMOVED_DEVICE:
+		if (dev->type == &i2c_client_type)
+			chromeos_laptop_detach_i2c_client(to_i2c_client(dev));
+		break;
 	}
 
-	return ret;
+	return 0;
 }
 
+static struct notifier_block chromeos_laptop_i2c_notifier = {
+	.notifier_call = chromeos_laptop_i2c_notifier_call,
+};
+
 static struct chromeos_laptop samsung_series_5_550 = {
 	.i2c_peripherals = {
 		/* Touchpad. */
@@ -322,7 +281,7 @@ static struct chromeos_laptop hp_chromebook_14 = {
 				.flags		= I2C_CLIENT_WAKE,
 			},
 			.dmi_name	= "trackpad",
-			.type		= I2C_ADAPTER_DESIGNWARE_0,
+			.type		= I2C_ADAPTER_DESIGNWARE,
 		},
 	},
 };
@@ -336,7 +295,7 @@ static struct chromeos_laptop dell_chromebook_11 = {
 				.flags		= I2C_CLIENT_WAKE,
 			},
 			.dmi_name	= "trackpad",
-			.type		= I2C_ADAPTER_DESIGNWARE_0,
+			.type		= I2C_ADAPTER_DESIGNWARE,
 		},
 		/* Elan Touchpad option. */
 		{
@@ -345,7 +304,7 @@ static struct chromeos_laptop dell_chromebook_11 = {
 				.flags		= I2C_CLIENT_WAKE,
 			},
 			.dmi_name	= "trackpad",
-			.type		= I2C_ADAPTER_DESIGNWARE_0,
+			.type		= I2C_ADAPTER_DESIGNWARE,
 		},
 	},
 };
@@ -359,7 +318,7 @@ static struct chromeos_laptop toshiba_cb35 = {
 				.flags		= I2C_CLIENT_WAKE,
 			},
 			.dmi_name	= "trackpad",
-			.type		= I2C_ADAPTER_DESIGNWARE_0,
+			.type		= I2C_ADAPTER_DESIGNWARE,
 		},
 	},
 };
@@ -401,7 +360,8 @@ static struct chromeos_laptop acer_c720 = {
 				.flags		= I2C_CLIENT_WAKE,
 			},
 			.dmi_name	= "touchscreen",
-			.type		= I2C_ADAPTER_DESIGNWARE_1,
+			.type		= I2C_ADAPTER_DESIGNWARE,
+			.pci_devid	= PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)),
 			.alt_addr	= ATMEL_TS_I2C_BL_ADDR,
 		},
 		/* Touchpad. */
@@ -411,7 +371,8 @@ static struct chromeos_laptop acer_c720 = {
 				.flags		= I2C_CLIENT_WAKE,
 			},
 			.dmi_name	= "trackpad",
-			.type		= I2C_ADAPTER_DESIGNWARE_0,
+			.type		= I2C_ADAPTER_DESIGNWARE,
+			.pci_devid	= PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)),
 		},
 		/* Elan Touchpad option. */
 		{
@@ -420,7 +381,8 @@ static struct chromeos_laptop acer_c720 = {
 				.flags		= I2C_CLIENT_WAKE,
 			},
 			.dmi_name	= "trackpad",
-			.type		= I2C_ADAPTER_DESIGNWARE_0,
+			.type		= I2C_ADAPTER_DESIGNWARE,
+			.pci_devid	= PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)),
 		},
 		/* Light Sensor. */
 		{
@@ -428,7 +390,8 @@ static struct chromeos_laptop acer_c720 = {
 				I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
 			},
 			.dmi_name	= "lightsensor",
-			.type		= I2C_ADAPTER_DESIGNWARE_1,
+			.type		= I2C_ADAPTER_DESIGNWARE,
+			.pci_devid	= PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)),
 		},
 	},
 };
@@ -546,14 +509,16 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
 };
 MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table);
 
-static struct platform_device *cros_platform_device;
+static int __init chromeos_laptop_scan_adapter(struct device *dev, void *data)
+{
+	struct i2c_adapter *adapter;
 
-static struct platform_driver cros_platform_driver = {
-	.driver = {
-		.name = "chromeos_laptop",
-	},
-	.probe = chromeos_laptop_probe,
-};
+	adapter = i2c_verify_adapter(dev);
+	if (adapter)
+		chromeos_laptop_check_adapter(adapter);
+
+	return 0;
+}
 
 static int __init chromeos_laptop_get_irq_from_dmi(const char *dmi_name)
 {
@@ -602,7 +567,7 @@ chromeos_laptop_prepare(const struct dmi_system_id *id)
 static int __init chromeos_laptop_init(void)
 {
 	const struct dmi_system_id *dmi_id;
-	int ret;
+	int error;
 
 	dmi_id = dmi_first_match(chromeos_laptop_dmi_table);
 	if (!dmi_id) {
@@ -616,27 +581,20 @@ static int __init chromeos_laptop_init(void)
 	if (IS_ERR(cros_laptop))
 		return PTR_ERR(cros_laptop);
 
-	ret = platform_driver_register(&cros_platform_driver);
-	if (ret)
-		return ret;
-
-	cros_platform_device = platform_device_alloc("chromeos_laptop", -1);
-	if (!cros_platform_device) {
-		ret = -ENOMEM;
-		goto fail_platform_device1;
+	error = bus_register_notifier(&i2c_bus_type,
+				      &chromeos_laptop_i2c_notifier);
+	if (error) {
+		pr_err("failed to register i2c bus notifier: %d\n", error);
+		return error;
 	}
 
-	ret = platform_device_add(cros_platform_device);
-	if (ret)
-		goto fail_platform_device2;
+	/*
+	 * Scan adapters that have been registered before we installed
+	 * the notifier to make sure we do not miss any devices.
+	 */
+	i2c_for_each_dev(NULL, chromeos_laptop_scan_adapter);
 
 	return 0;
-
-fail_platform_device2:
-	platform_device_put(cros_platform_device);
-fail_platform_device1:
-	platform_driver_unregister(&cros_platform_driver);
-	return ret;
 }
 
 static void __exit chromeos_laptop_exit(void)
@@ -644,8 +602,7 @@ static void __exit chromeos_laptop_exit(void)
 	struct i2c_peripheral *i2c_dev;
 	int i;
 
-	platform_device_unregister(cros_platform_device);
-	platform_driver_unregister(&cros_platform_driver);
+	bus_unregister_notifier(&i2c_bus_type, &chromeos_laptop_i2c_notifier);
 
 	for (i = 0; i < MAX_I2C_PERIPHERALS; i++) {
 		i2c_dev = &cros_laptop->i2c_peripherals[i];
@@ -654,7 +611,7 @@ static void __exit chromeos_laptop_exit(void)
 		if (!i2c_dev->board_info.type)
 			break;
 
-		if (i2c_dev->state == PROBED)
+		if (i2c_dev->client)
 			i2c_unregister_device(i2c_dev->client);
 	}
 }
