[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