diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index 431cf26..99cc529 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -8,6 +8,7 @@
 
 #include <common.h>
 #include <cros_ec.h>
+#include <dm.h>
 #include <ec_commands.h>
 #include <errno.h>
 #include <hash.h>
@@ -85,7 +86,7 @@ struct ec_state {
 	struct ec_keymatrix_entry *matrix;	/* the key matrix info */
 	uint8_t keyscan[KEYBOARD_COLS];
 	bool recovery_req;
-} s_state, *state;
+} s_state, *g_state;
 
 /**
  * cros_ec_read_state() - read the sandbox EC state from the state file
@@ -138,7 +139,7 @@ static int cros_ec_read_state(const void *blob, int node)
  */
 static int cros_ec_write_state(void *blob, int node)
 {
-	struct ec_state *ec = &s_state;
+	struct ec_state *ec = g_state;
 
 	/* We are guaranteed enough space to write basic properties */
 	fdt_setprop_u32(blob, node, "current-image", ec->current_image);
@@ -369,7 +370,7 @@ static int process_cmd(struct ec_state *ec,
 		struct fmap_entry *entry;
 		int ret, size;
 
-		entry = &state->ec_config.region[EC_FLASH_REGION_RW];
+		entry = &ec->ec_config.region[EC_FLASH_REGION_RW];
 
 		switch (req->cmd) {
 		case EC_VBOOT_HASH_RECALC:
@@ -426,7 +427,7 @@ static int process_cmd(struct ec_state *ec,
 		case EC_FLASH_REGION_RO:
 		case EC_FLASH_REGION_RW:
 		case EC_FLASH_REGION_WP_RO:
-			entry = &state->ec_config.region[req->region];
+			entry = &ec->ec_config.region[req->region];
 			resp->offset = entry->offset;
 			resp->size = entry->length;
 			len = sizeof(*resp);
@@ -466,16 +467,24 @@ static int process_cmd(struct ec_state *ec,
 	return len;
 }
 
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_sandbox_packet(struct udevice *udev, int out_bytes, int in_bytes)
+{
+	struct cros_ec_dev *dev = udev->uclass_priv;
+	struct ec_state *ec = dev_get_priv(dev->dev);
+#else
 int cros_ec_sandbox_packet(struct cros_ec_dev *dev, int out_bytes,
 			   int in_bytes)
 {
+	struct ec_state *ec = &s_state;
+#endif
 	struct ec_host_request *req_hdr = (struct ec_host_request *)dev->dout;
 	const void *req_data = req_hdr + 1;
 	struct ec_host_response *resp_hdr = (struct ec_host_response *)dev->din;
 	void *resp_data = resp_hdr + 1;
 	int len;
 
-	len = process_cmd(&s_state, req_hdr, req_data, resp_hdr, resp_data);
+	len = process_cmd(ec, req_hdr, req_data, resp_hdr, resp_data);
 	if (len < 0)
 		return len;
 
@@ -498,7 +507,11 @@ int cros_ec_sandbox_decode_fdt(struct cros_ec_dev *dev, const void *blob)
 
 void cros_ec_check_keyboard(struct cros_ec_dev *dev)
 {
+#ifdef CONFIG_DM_CROS_EC
+	struct ec_state *ec = dev_get_priv(dev->dev);
+#else
 	struct ec_state *ec = &s_state;
+#endif
 	ulong start;
 
 	printf("Press keys for EC to detect on reset (ESC=recovery)...");
@@ -512,6 +525,52 @@ void cros_ec_check_keyboard(struct cros_ec_dev *dev)
 	}
 }
 
+#ifdef CONFIG_DM_CROS_EC
+int cros_ec_probe(struct udevice *dev)
+{
+	struct ec_state *ec = dev->priv;
+	struct cros_ec_dev *cdev = dev->uclass_priv;
+	const void *blob = gd->fdt_blob;
+	int node;
+	int err;
+
+	memcpy(ec, &s_state, sizeof(*ec));
+	err = cros_ec_decode_ec_flash(blob, dev->of_offset, &ec->ec_config);
+	if (err)
+		return err;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
+	if (node < 0) {
+		debug("%s: No cros_ec keyboard found\n", __func__);
+	} else if (keyscan_read_fdt_matrix(ec, blob, node)) {
+		debug("%s: Could not read key matrix\n", __func__);
+		return -1;
+	}
+
+	/* If we loaded EC data, check that the length matches */
+	if (ec->flash_data &&
+	    ec->flash_data_len != ec->ec_config.flash.length) {
+		printf("EC data length is %x, expected %x, discarding data\n",
+		       ec->flash_data_len, ec->ec_config.flash.length);
+		os_free(ec->flash_data);
+		ec->flash_data = NULL;
+	}
+
+	/* Otherwise allocate the memory */
+	if (!ec->flash_data) {
+		ec->flash_data_len = ec->ec_config.flash.length;
+		ec->flash_data = os_malloc(ec->flash_data_len);
+		if (!ec->flash_data)
+			return -ENOMEM;
+	}
+
+	cdev->dev = dev;
+	g_state = ec;
+	return cros_ec_register(dev);
+}
+
+#else
+
 /**
  * Initialize sandbox EC emulation.
  *
@@ -562,3 +621,24 @@ int cros_ec_sandbox_init(struct cros_ec_dev *dev, const void *blob)
 
 	return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_CROS_EC
+struct dm_cros_ec_ops cros_ec_ops = {
+	.packet = cros_ec_sandbox_packet,
+};
+
+static const struct udevice_id cros_ec_ids[] = {
+	{ .compatible = "google,cros-ec" },
+	{ }
+};
+
+U_BOOT_DRIVER(cros_ec_sandbox) = {
+	.name		= "cros_ec",
+	.id		= UCLASS_CROS_EC,
+	.of_match	= cros_ec_ids,
+	.probe		= cros_ec_probe,
+	.priv_auto_alloc_size = sizeof(struct ec_state),
+	.ops		= &cros_ec_ops,
+};
+#endif
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 9adc5cc..2fd2c64 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -32,6 +32,7 @@
 #define CONFIG_DM_GPIO
 #define CONFIG_DM_TEST
 #define CONFIG_DM_SERIAL
+#define CONFIG_DM_CROS_EC
 
 #define CONFIG_SYS_STDIO_DEREGISTER
 
