dm: i2c: Add an explicit test mode to the sandbox I2C driver

At present this driver has a few test features. They are needed for running
the driver model unit tests but are confusing and unnecessary if using
sandbox at the command line. Add a flag to enable the test mode, and don't
enable it by default.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 296589c..06e7301 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -17,6 +17,16 @@
 #define SANDBOX_PCI_CLASS_CODE		PCI_CLASS_CODE_COMM
 #define SANDBOX_PCI_CLASS_SUB_CODE	PCI_CLASS_SUB_CODE_COMM_SERIAL
 
+/**
+ * sandbox_i2c_set_test_mode() - set test mode for running unit tests
+ *
+ * See sandbox_i2c_xfer() for the behaviour changes.
+ *
+ * @bus:	sandbox I2C bus to adjust
+ * @test_mode:	true to select test mode, false to run normally
+ */
+void sandbox_i2c_set_test_mode(struct udevice *bus, bool test_mode);
+
 enum sandbox_i2c_eeprom_test_mode {
 	SIE_TEST_MODE_NONE,
 	/* Permits read/write of only one byte per I2C transaction */
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
index 621caec..dd1c7e5 100644
--- a/drivers/i2c/sandbox_i2c.c
+++ b/drivers/i2c/sandbox_i2c.c
@@ -18,8 +18,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-struct dm_sandbox_i2c_emul_priv {
-	struct udevice *emul;
+struct sandbox_i2c_priv {
+	bool test_mode;
 };
 
 static int get_emul(struct udevice *dev, struct udevice **devp,
@@ -47,17 +47,25 @@
 	return 0;
 }
 
+void sandbox_i2c_set_test_mode(struct udevice *bus, bool test_mode)
+{
+	struct sandbox_i2c_priv *priv = dev_get_priv(bus);
+
+	priv->test_mode = test_mode;
+}
+
 static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
 			    int nmsgs)
 {
 	struct dm_i2c_bus *i2c = dev_get_uclass_priv(bus);
+	struct sandbox_i2c_priv *priv = dev_get_priv(bus);
 	struct dm_i2c_ops *ops;
 	struct udevice *emul, *dev;
 	bool is_read;
 	int ret;
 
 	/* Special test code to return success but with no emulation */
-	if (msg->addr == SANDBOX_I2C_TEST_ADDR)
+	if (priv->test_mode && msg->addr == SANDBOX_I2C_TEST_ADDR)
 		return 0;
 
 	ret = i2c_get_chip(bus, msg->addr, 1, &dev);
@@ -68,15 +76,18 @@
 	if (ret)
 		return ret;
 
-	/*
-	 * For testing, don't allow writing above 100KHz for writes and
-	 * 400KHz for reads
-	 */
-	is_read = nmsgs > 1;
-	if (i2c->speed_hz > (is_read ? 400000 : 100000)) {
-		debug("%s: Max speed exceeded\n", __func__);
-		return -EINVAL;
+	if (priv->test_mode) {
+		/*
+		* For testing, don't allow writing above 100KHz for writes and
+		* 400KHz for reads.
+		*/
+		is_read = nmsgs > 1;
+		if (i2c->speed_hz > (is_read ? 400000 : 100000)) {
+			debug("%s: Max speed exceeded\n", __func__);
+			return -EINVAL;
+		}
 	}
+
 	return ops->xfer(emul, msg, nmsgs);
 }
 
@@ -94,4 +105,5 @@
 	.id	= UCLASS_I2C,
 	.of_match = sandbox_i2c_ids,
 	.ops	= &sandbox_i2c_ops,
+	.priv_auto_alloc_size = sizeof(struct sandbox_i2c_priv),
 };
diff --git a/include/i2c.h b/include/i2c.h
index d794057..1e25986 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -54,6 +54,7 @@
 	uint flags;
 #ifdef CONFIG_SANDBOX
 	struct udevice *emul;
+	bool test_mode;
 #endif
 };
 
diff --git a/test/dm/i2c.c b/test/dm/i2c.c
index 541b73b..c5939a1 100644
--- a/test/dm/i2c.c
+++ b/test/dm/i2c.c
@@ -66,6 +66,9 @@
 	uint8_t buf[5];
 
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+
+	/* Use test mode so we create the required errors for invalid speeds */
+	sandbox_i2c_set_test_mode(bus, true);
 	ut_assertok(i2c_get_chip(bus, chip, 1, &dev));
 	ut_assertok(dm_i2c_set_bus_speed(bus, 100000));
 	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
@@ -73,6 +76,7 @@
 	ut_asserteq(400000, dm_i2c_get_bus_speed(bus));
 	ut_assertok(dm_i2c_read(dev, 0, buf, 5));
 	ut_asserteq(-EINVAL, dm_i2c_write(dev, 0, buf, 5));
+	sandbox_i2c_set_test_mode(bus, false);
 
 	return 0;
 }
@@ -100,7 +104,11 @@
 	struct udevice *bus, *dev;
 
 	ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus));
+
+	/* Use test mode so that this chip address will always probe */
+	sandbox_i2c_set_test_mode(bus, true);
 	ut_assertok(dm_i2c_probe(bus, SANDBOX_I2C_TEST_ADDR, 0, &dev));
+	sandbox_i2c_set_test_mode(bus, false);
 
 	return 0;
 }