summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Honscheid <honscheid@google.com>2022-09-26 16:17:00 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-10-04 19:18:34 +0000
commit23b4ab16f3f7e8f11f9198cfc35a722a2eaa3ef7 (patch)
tree52506751d99768cf90250f4102a183053eee5249
parent582fe20f727caa7aa5083cb1f35e9ac936b00485 (diff)
downloadchrome-ec-23b4ab16f3f7e8f11f9198cfc35a722a2eaa3ef7.tar.gz
zephyr: tests: Split off non-Zephyr i2c_controller.c console cmds
The console commands i2cspeed, i2cxfer, i2cscan are not used in Zephyr builds but are included in i2c_controller.c and count against our coverage stats. Move these to a new source file that is only included in legacy builds. This eliminates 122 SLOC. BRANCH=None BUG=b:248311206 TEST=make BOARD=brya -j LOW_COVERAGE_REASON=No new code, moving non-Zephyr code to new file Signed-off-by: Tristan Honscheid <honscheid@google.com> Change-Id: Ie6755924b3d9347797a4fb18f40815a3e96f75b9 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3919411 Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com> Reviewed-by: Keith Short <keithshort@chromium.org>
-rw-r--r--common/build.mk1
-rw-r--r--common/i2c_controller.c305
-rw-r--r--common/i2c_controller_cros_ec.c321
-rw-r--r--include/i2c_bitbang.h2
4 files changed, 324 insertions, 305 deletions
diff --git a/common/build.mk b/common/build.mk
index f784d57732..db078e8a79 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -103,6 +103,7 @@ common-$(CONFIG_HOSTCMD_RTC)+=rtc.o
common-$(CONFIG_I2C_DEBUG)+=i2c_trace.o
common-$(CONFIG_I2C_HID_TOUCHPAD)+=i2c_hid_touchpad.o
common-$(CONFIG_I2C_CONTROLLER)+=i2c_controller.o
+common-$(CONFIG_I2C_CONTROLLER)+=i2c_controller_cros_ec.o
common-$(CONFIG_I2C_PERIPHERAL)+=i2c_peripheral.o
common-$(CONFIG_I2C_BITBANG)+=i2c_bitbang.o
common-$(CONFIG_I2C_VIRTUAL_BATTERY)+=virtual_battery.o
diff --git a/common/i2c_controller.c b/common/i2c_controller.c
index 146d582c0d..e2f4149b16 100644
--- a/common/i2c_controller.c
+++ b/common/i2c_controller.c
@@ -1557,311 +1557,6 @@ DECLARE_CONSOLE_COMMAND(i2cprotect, command_i2cprotect, "[port]",
"Protect I2C bus");
#endif
-#ifdef CONFIG_CMD_I2C_SCAN
-static void scan_bus(int port, const char *desc)
-{
- int level;
- uint8_t tmp;
- uint16_t addr_flags;
-
- ccprintf("Scanning %d %s", port, desc);
-
- i2c_lock(port, 1);
-
- /* Don't scan a busy port, since reads will just fail / time out */
- level = i2c_get_line_levels(port);
- if (level != I2C_LINE_IDLE) {
- ccprintf(": port busy (SDA=%d, SCL=%d)",
- (level & I2C_LINE_SDA_HIGH) ? 1 : 0,
- (level & I2C_LINE_SCL_HIGH) ? 1 : 0);
- goto scan_bus_exit;
- }
- /*
- * Only scan in the valid client device address range, otherwise some
- * client devices stretch the clock in weird ways that prevent the
- * discovery of other devices.
- */
- for (addr_flags = I2C_FIRST_VALID_ADDR;
- addr_flags <= I2C_LAST_VALID_ADDR; ++addr_flags) {
- watchdog_reload(); /* Otherwise a full scan trips watchdog */
- ccputs(".");
-
- /* Do a single read */
- if (!i2c_xfer_unlocked(port, addr_flags, NULL, 0, &tmp, 1,
- I2C_XFER_SINGLE))
- ccprintf("\n 0x%02x", addr_flags);
- }
-
-scan_bus_exit:
- i2c_lock(port, 0);
- ccputs("\n");
-}
-
-static int command_scan(int argc, const char **argv)
-{
- int port;
- char *e;
- const struct i2c_port_t *i2c_port;
-
- if (argc == 1) {
- for (port = 0; port < i2c_ports_used; port++)
- scan_bus(i2c_ports[port].port, i2c_ports[port].name);
-
- if (IS_ENABLED(CONFIG_I2C_BITBANG))
- for (port = 0; port < i2c_bitbang_ports_used; port++)
- scan_bus(i2c_bitbang_ports[port].port,
- i2c_bitbang_ports[port].name);
-
- return EC_SUCCESS;
- }
-
- port = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- i2c_port = get_i2c_port(port);
- if (!i2c_port)
- return EC_ERROR_PARAM2;
-
- scan_bus(port, i2c_port->name);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(i2cscan, command_scan, "i2cscan [port]",
- "Scan I2C ports for devices");
-#endif
-
-#ifdef CONFIG_CMD_I2C_XFER
-static int command_i2cxfer(int argc, const char **argv)
-{
- int port;
- uint16_t addr_flags;
- uint16_t offset = 0;
- uint8_t offset_size = 0;
- int v = 0;
- uint8_t data[32];
- char *e;
- int rv = 0;
-
- if (argc < 5)
- return EC_ERROR_PARAM_COUNT;
-
- port = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- addr_flags = strtoi(argv[3], &e, 0);
- if (*e)
- return EC_ERROR_PARAM3;
-
- offset = strtoi(argv[4], &e, 0);
- if (*e)
- return EC_ERROR_PARAM4;
-
- offset_size = (strlen(argv[4]) == 6) ? 2 : 1;
-
- if (argc >= 6) {
- v = strtoi(argv[5], &e, 0);
- if (*e)
- return EC_ERROR_PARAM5;
- }
-
- if (strcasecmp(argv[1], "r") == 0) {
- /* 8-bit read */
- if (offset_size == 2)
- rv = i2c_read_offset16(port, addr_flags, offset, &v, 1);
- else
- rv = i2c_read8(port, addr_flags, offset, &v);
- if (!rv)
- ccprintf("0x%02x [%d]\n", v, v);
-
- } else if (strcasecmp(argv[1], "r16") == 0) {
- /* 16-bit read */
- if (offset_size == 2)
- rv = i2c_read_offset16(port, addr_flags, offset, &v, 2);
- else
- rv = i2c_read16(port, addr_flags, offset, &v);
- if (!rv)
- ccprintf("0x%04x [%d]\n", v, v);
-
- } else if (strcasecmp(argv[1], "rlen") == 0) {
- /* Arbitrary length read; param5 = len */
- if (argc < 6 || v < 0 || v > sizeof(data))
- return EC_ERROR_PARAM5;
-
- rv = i2c_xfer(port, addr_flags, (uint8_t *)&offset, 1, data, v);
-
- if (!rv) {
- char str_buf[hex_str_buf_size(v)];
-
- snprintf_hex_buffer(str_buf, sizeof(str_buf),
- HEX_BUF(data, v));
- ccprintf("Data: %s\n", str_buf);
- }
-
- } else if (strcasecmp(argv[1], "w") == 0) {
- /* 8-bit write */
- if (argc < 6)
- return EC_ERROR_PARAM5;
- if (offset_size == 2)
- rv = i2c_write_offset16(port, addr_flags, offset, v, 1);
- else
- rv = i2c_write8(port, addr_flags, offset, v);
-
- } else if (strcasecmp(argv[1], "w16") == 0) {
- /* 16-bit write */
- if (argc < 6)
- return EC_ERROR_PARAM5;
- if (offset_size == 2)
- rv = i2c_write_offset16(port, addr_flags, offset, v, 2);
- else
- rv = i2c_write16(port, addr_flags, offset, v);
-#ifdef CONFIG_CMD_I2C_XFER_RAW
- } else if (strcasecmp(argv[1], "raw") == 0) {
- /* <port> <addr_flags> <read_count> [write_bytes..] */
- int i;
- int write_count = 0, read_count = 0;
- int xferflags = I2C_XFER_START;
-
- read_count = offset;
- if (read_count < 0 || read_count > sizeof(data))
- return EC_ERROR_PARAM5;
-
- if (argc >= 6) {
- /* Parse bytes to write */
- argc -= 5;
- argv += 5;
- write_count = argc;
- if (write_count > sizeof(data)) {
- ccprintf("Too many bytes to write\n");
- return EC_ERROR_PARAM_COUNT;
- }
-
- for (i = 0; i < write_count; i++) {
- data[i] = strtoi(argv[i], &e, 0);
- if (*e) {
- ccprintf("Bad write byte %d\n", i);
- return EC_ERROR_INVAL;
- }
- }
- }
-
- if (write_count) {
- if (read_count == 0)
- xferflags |= I2C_XFER_STOP;
- ccprintf("Writing %d bytes\n", write_count);
- i2c_lock(port, 1);
- rv = i2c_xfer_unlocked(port, addr_flags, data,
- write_count, NULL, 0, xferflags);
- if (rv || read_count == 0) {
- i2c_lock(port, 0);
- return rv;
- }
- }
- if (read_count) {
- ccprintf("Reading %d bytes\n", read_count);
- if (write_count == 0)
- i2c_lock(port, 1);
- rv = i2c_xfer_unlocked(port, addr_flags, NULL, 0, data,
- read_count,
- I2C_XFER_START | I2C_XFER_STOP);
- i2c_lock(port, 0);
- if (!rv) {
- char str_buf[hex_str_buf_size(read_count)];
-
- snprintf_hex_buffer(str_buf, sizeof(str_buf),
- HEX_BUF(data, read_count));
- ccprintf("Data: %s\n", str_buf);
- }
- }
-#endif /* CONFIG_CMD_I2C_XFER_RAW */
- } else {
- return EC_ERROR_PARAM1;
- }
-
- return rv;
-}
-DECLARE_CONSOLE_COMMAND(i2cxfer, command_i2cxfer,
- "r/r16/rlen/w/w16 port addr offset [value | len]"
-#ifdef CONFIG_CMD_I2C_XFER_RAW
- "\nraw port addr read_count [bytes_to_write..]"
-#endif /* CONFIG_CMD_I2C_XFER_RAW */
- ,
- "Read write I2C");
-#endif
-
-#ifdef CONFIG_CMD_I2C_SPEED
-
-static const char *const i2c_freq_str[] = {
- [I2C_FREQ_1000KHZ] = "1000 kHz",
- [I2C_FREQ_400KHZ] = "400 kHz",
- [I2C_FREQ_100KHZ] = "100 kHz",
- [I2C_FREQ_COUNT] = "unknown",
-};
-
-BUILD_ASSERT(ARRAY_SIZE(i2c_freq_str) == I2C_FREQ_COUNT + 1);
-
-static int command_i2c_speed(int argc, const char **argv)
-{
- int port;
- char *e;
- enum i2c_freq freq;
- enum i2c_freq new_freq = I2C_FREQ_COUNT;
-
- if (argc < 2 || argc > 3)
- return EC_ERROR_PARAM_COUNT;
-
- port = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
-
- if (port < 0 || port >= I2C_PORT_COUNT)
- return EC_ERROR_INVAL;
-
- freq = i2c_get_freq(port);
- if (freq < 0 || freq > I2C_FREQ_COUNT)
- return EC_ERROR_UNKNOWN;
-
- if (argc == 3) {
- int khz;
- int rv;
-
- khz = strtoi(argv[2], &e, 0);
- if (*e)
- return EC_ERROR_PARAM2;
-
- switch (khz) {
- case 100:
- new_freq = I2C_FREQ_100KHZ;
- break;
- case 400:
- new_freq = I2C_FREQ_400KHZ;
- break;
- case 1000:
- new_freq = I2C_FREQ_1000KHZ;
- break;
- default:
- return EC_ERROR_PARAM2;
- }
- rv = i2c_set_freq(port, new_freq);
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- if (new_freq != I2C_FREQ_COUNT)
- ccprintf("Port %d speed changed from %s to %s\n", port,
- i2c_freq_str[freq], i2c_freq_str[new_freq]);
- else
- ccprintf("Port %d speed is %s\n", port, i2c_freq_str[freq]);
-
- return EC_SUCCESS;
-}
-
-DECLARE_CONSOLE_COMMAND(i2cspeed, command_i2c_speed, "port [speed in kHz]",
- "Get or set I2C port speed");
-
-#endif /* CONFIG_CMD_I2C_SPEED */
-
#ifdef CONFIG_CMD_I2C_STRESS_TEST
static void i2c_test_status(struct i2c_test_results *i2c_test, int test_dev)
{
diff --git a/common/i2c_controller_cros_ec.c b/common/i2c_controller_cros_ec.c
new file mode 100644
index 0000000000..e8c25e14ca
--- /dev/null
+++ b/common/i2c_controller_cros_ec.c
@@ -0,0 +1,321 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "i2c_bitbang.h"
+#include "i2c_private.h"
+#include "i2c.h"
+#include "console.h"
+#include "watchdog.h"
+#include "printf.h"
+#include "util.h"
+
+/* This source file contains I2C controller code that is used only in legacy
+ * (CrOS EC) builds.
+ */
+
+#ifdef CONFIG_CMD_I2C_SCAN
+static void scan_bus(int port, const char *desc)
+{
+ int level;
+ uint8_t tmp;
+ uint16_t addr_flags;
+
+ ccprintf("Scanning %d %s", port, desc);
+
+ i2c_lock(port, 1);
+
+ /* Don't scan a busy port, since reads will just fail / time out */
+ level = i2c_get_line_levels(port);
+ if (level != I2C_LINE_IDLE) {
+ ccprintf(": port busy (SDA=%d, SCL=%d)",
+ (level & I2C_LINE_SDA_HIGH) ? 1 : 0,
+ (level & I2C_LINE_SCL_HIGH) ? 1 : 0);
+ goto scan_bus_exit;
+ }
+ /*
+ * Only scan in the valid client device address range, otherwise some
+ * client devices stretch the clock in weird ways that prevent the
+ * discovery of other devices.
+ */
+ for (addr_flags = I2C_FIRST_VALID_ADDR;
+ addr_flags <= I2C_LAST_VALID_ADDR; ++addr_flags) {
+ watchdog_reload(); /* Otherwise a full scan trips watchdog */
+ ccputs(".");
+
+ /* Do a single read */
+ if (!i2c_xfer_unlocked(port, addr_flags, NULL, 0, &tmp, 1,
+ I2C_XFER_SINGLE))
+ ccprintf("\n 0x%02x", addr_flags);
+ }
+
+scan_bus_exit:
+ i2c_lock(port, 0);
+ ccputs("\n");
+}
+
+static int command_scan(int argc, const char **argv)
+{
+ int port;
+ char *e;
+ const struct i2c_port_t *i2c_port;
+
+ if (argc == 1) {
+ for (port = 0; port < i2c_ports_used; port++)
+ scan_bus(i2c_ports[port].port, i2c_ports[port].name);
+
+ if (IS_ENABLED(CONFIG_I2C_BITBANG))
+ for (port = 0; port < i2c_bitbang_ports_used; port++)
+ scan_bus(i2c_bitbang_ports[port].port,
+ i2c_bitbang_ports[port].name);
+
+ return EC_SUCCESS;
+ }
+
+ port = strtoi(argv[1], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM2;
+
+ i2c_port = get_i2c_port(port);
+ if (!i2c_port)
+ return EC_ERROR_PARAM2;
+
+ scan_bus(port, i2c_port->name);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(i2cscan, command_scan, "i2cscan [port]",
+ "Scan I2C ports for devices");
+#endif
+
+#ifdef CONFIG_CMD_I2C_XFER
+static int command_i2cxfer(int argc, const char **argv)
+{
+ int port;
+ uint16_t addr_flags;
+ uint16_t offset = 0;
+ uint8_t offset_size = 0;
+ int v = 0;
+ uint8_t data[32];
+ char *e;
+ int rv = 0;
+
+ if (argc < 5)
+ return EC_ERROR_PARAM_COUNT;
+
+ port = strtoi(argv[2], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM2;
+
+ addr_flags = strtoi(argv[3], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM3;
+
+ offset = strtoi(argv[4], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM4;
+
+ offset_size = (strlen(argv[4]) == 6) ? 2 : 1;
+
+ if (argc >= 6) {
+ v = strtoi(argv[5], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM5;
+ }
+
+ if (strcasecmp(argv[1], "r") == 0) {
+ /* 8-bit read */
+ if (offset_size == 2)
+ rv = i2c_read_offset16(port, addr_flags, offset, &v, 1);
+ else
+ rv = i2c_read8(port, addr_flags, offset, &v);
+ if (!rv)
+ ccprintf("0x%02x [%d]\n", v, v);
+
+ } else if (strcasecmp(argv[1], "r16") == 0) {
+ /* 16-bit read */
+ if (offset_size == 2)
+ rv = i2c_read_offset16(port, addr_flags, offset, &v, 2);
+ else
+ rv = i2c_read16(port, addr_flags, offset, &v);
+ if (!rv)
+ ccprintf("0x%04x [%d]\n", v, v);
+
+ } else if (strcasecmp(argv[1], "rlen") == 0) {
+ /* Arbitrary length read; param5 = len */
+ if (argc < 6 || v < 0 || v > sizeof(data))
+ return EC_ERROR_PARAM5;
+
+ rv = i2c_xfer(port, addr_flags, (uint8_t *)&offset, 1, data, v);
+
+ if (!rv) {
+ char str_buf[hex_str_buf_size(v)];
+
+ snprintf_hex_buffer(str_buf, sizeof(str_buf),
+ HEX_BUF(data, v));
+ ccprintf("Data: %s\n", str_buf);
+ }
+
+ } else if (strcasecmp(argv[1], "w") == 0) {
+ /* 8-bit write */
+ if (argc < 6)
+ return EC_ERROR_PARAM5;
+ if (offset_size == 2)
+ rv = i2c_write_offset16(port, addr_flags, offset, v, 1);
+ else
+ rv = i2c_write8(port, addr_flags, offset, v);
+
+ } else if (strcasecmp(argv[1], "w16") == 0) {
+ /* 16-bit write */
+ if (argc < 6)
+ return EC_ERROR_PARAM5;
+ if (offset_size == 2)
+ rv = i2c_write_offset16(port, addr_flags, offset, v, 2);
+ else
+ rv = i2c_write16(port, addr_flags, offset, v);
+#ifdef CONFIG_CMD_I2C_XFER_RAW
+ } else if (strcasecmp(argv[1], "raw") == 0) {
+ /* <port> <addr_flags> <read_count> [write_bytes..] */
+ int i;
+ int write_count = 0, read_count = 0;
+ int xferflags = I2C_XFER_START;
+
+ read_count = offset;
+ if (read_count < 0 || read_count > sizeof(data))
+ return EC_ERROR_PARAM5;
+
+ if (argc >= 6) {
+ /* Parse bytes to write */
+ argc -= 5;
+ argv += 5;
+ write_count = argc;
+ if (write_count > sizeof(data)) {
+ ccprintf("Too many bytes to write\n");
+ return EC_ERROR_PARAM_COUNT;
+ }
+
+ for (i = 0; i < write_count; i++) {
+ data[i] = strtoi(argv[i], &e, 0);
+ if (*e) {
+ ccprintf("Bad write byte %d\n", i);
+ return EC_ERROR_INVAL;
+ }
+ }
+ }
+
+ if (write_count) {
+ if (read_count == 0)
+ xferflags |= I2C_XFER_STOP;
+ ccprintf("Writing %d bytes\n", write_count);
+ i2c_lock(port, 1);
+ rv = i2c_xfer_unlocked(port, addr_flags, data,
+ write_count, NULL, 0, xferflags);
+ if (rv || read_count == 0) {
+ i2c_lock(port, 0);
+ return rv;
+ }
+ }
+ if (read_count) {
+ ccprintf("Reading %d bytes\n", read_count);
+ if (write_count == 0)
+ i2c_lock(port, 1);
+ rv = i2c_xfer_unlocked(port, addr_flags, NULL, 0, data,
+ read_count,
+ I2C_XFER_START | I2C_XFER_STOP);
+ i2c_lock(port, 0);
+ if (!rv) {
+ char str_buf[hex_str_buf_size(read_count)];
+
+ snprintf_hex_buffer(str_buf, sizeof(str_buf),
+ HEX_BUF(data, read_count));
+ ccprintf("Data: %s\n", str_buf);
+ }
+ }
+#endif /* CONFIG_CMD_I2C_XFER_RAW */
+ } else {
+ return EC_ERROR_PARAM1;
+ }
+
+ return rv;
+}
+DECLARE_CONSOLE_COMMAND(i2cxfer, command_i2cxfer,
+ "r/r16/rlen/w/w16 port addr offset [value | len]"
+#ifdef CONFIG_CMD_I2C_XFER_RAW
+ "\nraw port addr read_count [bytes_to_write..]"
+#endif /* CONFIG_CMD_I2C_XFER_RAW */
+ ,
+ "Read write I2C");
+#endif
+
+#ifdef CONFIG_CMD_I2C_SPEED
+
+static const char *const i2c_freq_str[] = {
+ [I2C_FREQ_1000KHZ] = "1000 kHz",
+ [I2C_FREQ_400KHZ] = "400 kHz",
+ [I2C_FREQ_100KHZ] = "100 kHz",
+ [I2C_FREQ_COUNT] = "unknown",
+};
+
+BUILD_ASSERT(ARRAY_SIZE(i2c_freq_str) == I2C_FREQ_COUNT + 1);
+
+static int command_i2c_speed(int argc, const char **argv)
+{
+ int port;
+ char *e;
+ enum i2c_freq freq;
+ enum i2c_freq new_freq = I2C_FREQ_COUNT;
+
+ if (argc < 2 || argc > 3)
+ return EC_ERROR_PARAM_COUNT;
+
+ port = strtoi(argv[1], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM1;
+
+ if (port < 0 || port >= I2C_PORT_COUNT)
+ return EC_ERROR_INVAL;
+
+ freq = i2c_get_freq(port);
+ if (freq < 0 || freq > I2C_FREQ_COUNT)
+ return EC_ERROR_UNKNOWN;
+
+ if (argc == 3) {
+ int khz;
+ int rv;
+
+ khz = strtoi(argv[2], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM2;
+
+ switch (khz) {
+ case 100:
+ new_freq = I2C_FREQ_100KHZ;
+ break;
+ case 400:
+ new_freq = I2C_FREQ_400KHZ;
+ break;
+ case 1000:
+ new_freq = I2C_FREQ_1000KHZ;
+ break;
+ default:
+ return EC_ERROR_PARAM2;
+ }
+ rv = i2c_set_freq(port, new_freq);
+ if (rv != EC_SUCCESS)
+ return rv;
+ }
+
+ if (new_freq != I2C_FREQ_COUNT)
+ ccprintf("Port %d speed changed from %s to %s\n", port,
+ i2c_freq_str[freq], i2c_freq_str[new_freq]);
+ else
+ ccprintf("Port %d speed is %s\n", port, i2c_freq_str[freq]);
+
+ return EC_SUCCESS;
+}
+
+DECLARE_CONSOLE_COMMAND(i2cspeed, command_i2c_speed, "port [speed in kHz]",
+ "Get or set I2C port speed");
+
+#endif /* CONFIG_CMD_I2C_SPEED */
diff --git a/include/i2c_bitbang.h b/include/i2c_bitbang.h
index cc9b5cbc11..9c7c730518 100644
--- a/include/i2c_bitbang.h
+++ b/include/i2c_bitbang.h
@@ -5,6 +5,8 @@
#ifndef __CROS_EC_I2C_BITBANG_H
#define __CROS_EC_I2C_BITBANG_H
+#include <stdbool.h>
+
#include "i2c.h"
extern const struct i2c_drv bitbang_drv;