From: Denis Zalevskiy <denis.zalevs...@ge.com>

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

Signed-off-by: Denis Zalevskiy <denis.zalevs...@ge.com>
Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.com>
---
 drivers/bootcount/Kconfig         | 15 ++++++++-
 drivers/bootcount/bootcount_i2c.c | 71 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig
index 9a0bd51..f67f518 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.
 
@@ -127,4 +129,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 496741d..a1fc219 100644
--- a/drivers/bootcount/bootcount_i2c.c
+++ b/drivers/bootcount/bootcount_i2c.c
@@ -8,36 +8,91 @@
 #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 void bootcount_set_bus(void) { return ; }
+
+static inline int bootcount_set_bus_back(int prev_bus __attribute__((unused)))
+{
+       return 0;
+}
+#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;
 }
-- 
1.8.3.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to