dev/i2c_bus: Add declaration, implementation of i2c_dev_detect()

This patch adds the I2C equivalent of an SMBus quick write to an I2C
device, which is used by some I2C drivers as a way to probe the
existence (or absence) of a certain device on the bus, based on
whether or not a 0-byte write to an I2C address is ACKed or NACKed.

i2c_dev_detect() is implemented using the existing i2c bus ops transfer()
function, so no further work is needed for existing controller drivers
to utilize this functionality.

Change-Id: I9b22bdc0343c846b235339f85d9f70b20f0f2bdd
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/64537
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@tutanota.com>
diff --git a/src/device/i2c_bus.c b/src/device/i2c_bus.c
index a63086c..c355506 100644
--- a/src/device/i2c_bus.c
+++ b/src/device/i2c_bus.c
@@ -6,6 +6,12 @@
 #include <device/i2c_bus.h>
 #include <commonlib/endian.h>
 
+bool i2c_dev_detect(struct device *dev, unsigned int addr)
+{
+	struct i2c_msg seg = { .flags = 0, .slave = addr, .buf = NULL, .len = 0 };
+	return dev->ops->ops_i2c_bus->transfer(dev, &seg, 0) == 0;
+}
+
 struct bus *i2c_link(const struct device *const dev)
 {
 	if (!dev || !dev->bus)
diff --git a/src/include/device/i2c_bus.h b/src/include/device/i2c_bus.h
index 42f461d..1a7e777 100644
--- a/src/include/device/i2c_bus.h
+++ b/src/include/device/i2c_bus.h
@@ -13,6 +13,11 @@
 	int (*transfer)(struct device *, const struct i2c_msg *, size_t count);
 };
 
+/**
+ * Determine device presence at a given slave address.
+ */
+bool i2c_dev_detect(struct device *dev, unsigned int addr);
+
 /*
  * Returns the first upstream facing link whose bus implements either
  * `i2c_bus_operations` *or* `smbus_bus_operations`.