[U-Boot] [PATCH 3/6] bootcount: i2c: Add bus switching to the I2C bootcount driver

Sebastian Reichel sebastian.reichel at collabora.co.uk
Tue Jun 26 17:43:01 UTC 2018


From: Denis Zalevskiy <denis.zalevskiy at ge.com>

If there is an I2C mux, current bus should be switched before manipulating with
I2C.

Signed-off-by: Denis Zalevskiy <denis.zalevskiy at ge.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel at collabora.co.uk>
---
 drivers/bootcount/Kconfig         | 15 ++++++-
 drivers/bootcount/bootcount_i2c.c | 70 +++++++++++++++++++++++++++----
 2 files changed, 76 insertions(+), 9 deletions(-)

diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig
index d335ed14b961..a5349a62fdc3 100644
--- a/drivers/bootcount/Kconfig
+++ b/drivers/bootcount/Kconfig
@@ -62,7 +62,9 @@ config BOOTCOUNT_I2C
 	bool "Boot counter on I2C device"
 	help
 	  Enable support for the bootcounter on an i2c (like RTC) device.
-	  CONFIG_SYS_I2C_RTC_ADDR = i2c chip address
+	  CONFIG_SYS_BOOTCOUNT_I2C_BUS = bus of the target I2C device,
+	                                 CONFIG_SYS_I2C_RTC_ADDR is used as fallback
+	  CONFIG_SYS_BOOTCOUNT_I2C_ADDR = target I2C device address
 	  CONFIG_SYS_BOOTCOUNT_ADDR = i2c addr which is used for
 	                              the bootcounter.
 
@@ -119,4 +121,15 @@ config SYS_BOOTCOUNT_ADDR
 	help
 	  Set the address used for reading and writing the boot counter.
 
+config SYS_BOOTCOUNT_I2C_BUS
+	int "I2C bootcounter device bus"
+	depends on BOOTCOUNT_I2C
+	help
+	  I2C bus of the device used to store bootcounter
+
+config SYS_BOOTCOUNT_I2C_ADDR
+	hex "I2C bootcounter device address"
+	depends on BOOTCOUNT_I2C
+	help
+	  I2C address of the device used to store bootcounter
 endif
diff --git a/drivers/bootcount/bootcount_i2c.c b/drivers/bootcount/bootcount_i2c.c
index e27b168c55cc..79d82ad451f3 100644
--- a/drivers/bootcount/bootcount_i2c.c
+++ b/drivers/bootcount/bootcount_i2c.c
@@ -9,36 +9,90 @@
 #include <linux/compiler.h>
 #include <i2c.h>
 
+#ifndef CONFIG_SYS_BOOTCOUNT_I2C_ADDR
+/* compatibility with the previous logic:
+ * previous version of driver used RTC device to store bootcount
+ */
+#define CONFIG_SYS_BOOTCOUNT_I2C_ADDR CONFIG_SYS_I2C_RTC_ADDR
+#endif
+
 #define BC_MAGIC	0xbc
 
+#ifdef CONFIG_SYS_BOOTCOUNT_I2C_BUS
+static int bootcount_set_bus(void)
+{
+	unsigned int current_bus = i2c_get_bus_num();
+
+	assert(current_bus <= INT_MAX);
+
+	int res = i2c_set_bus_num(CONFIG_SYS_BOOTCOUNT_I2C_BUS);
+
+	if (res < 0) {
+		puts("Error switching I2C bus\n");
+		return res;
+	}
+	return (int)current_bus;
+}
+
+static void bootcount_set_bus_back(int prev_bus)
+{
+	if (i2c_set_bus_num(prev_bus) < 0)
+		puts("Can't switch I2C bus back\n");
+}
+#else
+static inline int bootcount_set_bus(void) { return 0; }
+
+static inline void bootcount_set_bus_back(int prev_bus __attribute__((unused)))
+{
+}
+#endif
+
 void bootcount_store(ulong a)
 {
+	int prev_i2c_bus = bootcount_set_bus();
+
+	if (prev_i2c_bus < 0)
+		return;
+
 	unsigned char buf[3];
 	int ret;
 
 	buf[0] = BC_MAGIC;
 	buf[1] = (a & 0xff);
-	ret = i2c_write(CONFIG_SYS_I2C_RTC_ADDR, CONFIG_SYS_BOOTCOUNT_ADDR,
-		  CONFIG_BOOTCOUNT_ALEN, buf, 2);
+	ret = i2c_write(CONFIG_SYS_BOOTCOUNT_I2C_ADDR,
+			CONFIG_SYS_BOOTCOUNT_ADDR,
+			CONFIG_BOOTCOUNT_ALEN, buf, 2);
 	if (ret != 0)
 		puts("Error writing bootcount\n");
+
+	bootcount_set_bus_back(prev_i2c_bus);
 }
 
 ulong bootcount_load(void)
 {
+	ulong count = 0;
+
+	int prev_i2c_bus = bootcount_set_bus();
+
+	if (prev_i2c_bus < 0)
+		return count;
+
 	unsigned char buf[3];
 	int ret;
 
-	ret = i2c_read(CONFIG_SYS_I2C_RTC_ADDR, CONFIG_SYS_BOOTCOUNT_ADDR,
+	ret = i2c_read(CONFIG_SYS_BOOTCOUNT_I2C_ADDR,
+		       CONFIG_SYS_BOOTCOUNT_ADDR,
 		       CONFIG_BOOTCOUNT_ALEN, buf, 2);
 	if (ret != 0) {
 		puts("Error loading bootcount\n");
-		return 0;
+		goto out;
 	}
 	if (buf[0] == BC_MAGIC)
-		return buf[1];
-
-	bootcount_store(0);
+		count = buf[1];
+	else
+		bootcount_store(count);
 
-	return 0;
+out:
+	bootcount_set_bus_back(prev_i2c_bus);
+	return count;
 }
-- 
2.18.0



More information about the U-Boot mailing list