diff --git a/drivers/of/hw_prober.c b/drivers/of/hw_prober.c
index 442da6eff896..4345e5aed6d8 100644
--- a/drivers/of/hw_prober.c
+++ b/drivers/of/hw_prober.c
@@ -8,6 +8,7 @@
 #include <linux/array_size.h>
 #include <linux/i2c.h>
 #include <linux/of.h>
+#include <linux/of_graph.h>
 #include <linux/platform_device.h>
 
 #define DRV_NAME	"hw_prober"
@@ -108,9 +109,168 @@ static int i2c_component_prober(struct platform_device *pdev, const void *data)
 	return ret;
 }
 
+static int cros_get_coreboot_sku_id(struct device *dev, u32 *sku_id)
+{
+	struct device_node *node = NULL;
+	int ret;
+
+	node = of_find_node_by_path("/firmware/coreboot");
+	if (!node)
+		return dev_err_probe(dev, -EINVAL, "Cannot find coreboot firmware node\n");
+
+	ret = of_property_read_u32(node, "sku-id", sku_id);
+	if (ret)
+		dev_err_probe(dev, ret, "Cannot get SKU ID\n");
+
+	of_node_put(node);
+	return ret;
+}
+
+struct cros_sku_option {
+	u32	sku_id_val;
+	u32	sku_id_mask;
+	const char *compatible;
+};
+
+struct cros_sku_component_data {
+	const struct cros_sku_option *options;
+	int num_options;
+};
+
+/*
+ * cros_sku_component_selector - Selectively enable a component based on SKU ID
+ *
+ * Based on the list of component options and SKU ID read back from the device
+ * tree, enable the matching component. Also update the OF graph if it exists,
+ * so that the enabled component's remote endpoint correctly points to it. This
+ * assumes a single local endpoint, which should be the case for panels and
+ * camera sensors.
+ */
+static int cros_sku_component_selector(struct platform_device *pdev, const void *data)
+{
+	const struct cros_sku_component_data *pdata = data;
+	const char *compatible;
+	struct device_node *node = NULL, *endpoint = NULL, *remote = NULL;
+	struct property *status_prop = NULL, *endpoint_prop = NULL;
+	struct of_changeset *ocs = NULL;
+	__be32 *val = NULL;
+	int ret, i;
+	u32 sku_id;
+
+	if (!data)
+		return dev_err_probe(&pdev->dev, -EINVAL, "No data given\n");
+
+	ret = cros_get_coreboot_sku_id(&pdev->dev, &sku_id);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < pdata->num_options; i++)
+		if ((sku_id & pdata->options[i].sku_id_mask) == pdata->options[i].sku_id_val) {
+			compatible = pdata->options->compatible;
+			break;
+		}
+
+	if (i == pdata->num_options)
+		return dev_err_probe(&pdev->dev, -EINVAL, "Unknown SKU ID: 0x%x\n", sku_id);
+
+	node = of_find_compatible_node(NULL, NULL, compatible);
+	if (!node)
+		return dev_err_probe(&pdev->dev, -ENODEV, "Cannot find matching device node\n");
+
+	/* device node not marked as fail; don't mess with the device tree */
+	if (!of_device_is_fail(node))
+		goto err_free;
+
+	dev_info(&pdev->dev, "Enabling %pOF for SKU 0x%x\n", node, sku_id);
+
+	ret = -ENOMEM;
+	ocs = kzalloc(sizeof(*ocs), GFP_KERNEL);
+	if (!ocs)
+		goto err_free;
+
+	status_prop = kzalloc(sizeof(*status_prop), GFP_KERNEL);
+	if (!status_prop)
+		goto err_free;
+
+	status_prop->name   = "status";
+	status_prop->length = 5;
+	status_prop->value  = "okay";
+
+	/* Create changeset to apply DT changes atomically */
+	of_changeset_init(ocs);
+
+	if (of_graph_is_present(node)) {
+		ret = -EINVAL;
+
+		/* This currently assumes a single port on the component. */
+		endpoint = of_graph_get_next_endpoint(node, NULL);
+		if (!endpoint) {
+			dev_err(&pdev->dev, "No endpoint found for %pOF\n", node);
+			goto err_destroy_ocs;
+		}
+
+		remote = of_graph_get_remote_endpoint(endpoint);
+		if (!remote) {
+			dev_err(&pdev->dev, "No remote endpoint node found for %pOF\n", endpoint);
+			goto err_destroy_ocs;
+		}
+
+		endpoint_prop = kzalloc(sizeof(*endpoint_prop), GFP_KERNEL);
+		if (!endpoint_prop)
+			goto err_destroy_ocs;
+
+		val = kzalloc(sizeof(*val), GFP_KERNEL);
+		if (!val)
+			goto err_destroy_ocs;
+
+		*val = cpu_to_be32(endpoint->phandle);
+		endpoint_prop->name   = "remote-endpoint";
+		endpoint_prop->length = sizeof(*val);
+		endpoint_prop->value  = val;
+
+		ret = of_changeset_update_property(ocs, node, endpoint_prop);
+		if (ret)
+			goto err_destroy_ocs;
+	}
+
+	ret = of_changeset_update_property(ocs, node, status_prop);
+	if (ret)
+		goto err_destroy_ocs;
+	ret = of_changeset_apply(ocs);
+	if (ret)
+		goto err_destroy_ocs;
+
+	of_node_put(node);
+
+	return 0;
+
+err_destroy_ocs:
+	of_node_put(remote);
+	of_node_put(endpoint);
+	kfree(val);
+	kfree(endpoint_prop);
+	of_changeset_destroy(ocs);
+err_free:
+	kfree(ocs);
+	kfree(status_prop);
+	of_node_put(node);
+	return ret;
+}
+
+static const struct cros_sku_option cros_krane_panel_options[] = {
+	{ .sku_id_val = 0x00, .sku_id_mask = 0xf0, .compatible = "auo,kd101n80-45na" },
+	{ .sku_id_val = 0xb0, .sku_id_mask = 0xf0, .compatible = "boe,tv101wum-nl6" },
+};
+
+static const struct cros_sku_component_data cros_krane_panel_data = {
+	.options     = cros_krane_panel_options,
+	.num_options = ARRAY_SIZE(cros_krane_panel_options),
+};
+
 static const struct hw_prober_entry hw_prober_platforms[] = {
 	{ .compatible = "google,hana", .prober = i2c_component_prober, .data = "touchscreen" },
 	{ .compatible = "google,hana", .prober = i2c_component_prober, .data = "trackpad" },
+	{ .compatible = "google,krane", .prober = cros_sku_component_selector, .data = &cros_krane_panel_data },
 };
 
 static int hw_prober_probe(struct platform_device *pdev)
