diff options
author | Yuval Peress <peress@chromium.org> | 2020-10-28 10:20:08 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-11-08 03:41:10 +0000 |
commit | 25ae7edffcceb662d5d2ebe92d19bf6f191d8bd5 (patch) | |
tree | 148d8136c062dab69d4a2670f82f87d8d895f07c | |
parent | df5f77987d6707936c13a0e2fee09ddbd84c627a (diff) | |
download | chrome-ec-25ae7edffcceb662d5d2ebe92d19bf6f191d8bd5.tar.gz |
Add chip-specific shim along with i2c module
This change accomplishes 2 things:
1. It refactors the zephyr/shim directory to structure around
chip specific compilation. In this example, we're focusing
on npcx7m6fb which is used in volteer but others can be
added easily.
2. It shims the common/i2c_master.c by providing an alternate
implementation of i2c_xfer_unlocked that calls down to the
Zephyr API i2c_write_read instead of the chip specific
i2c_xfer_no_retry or chip_i2c_xfer_with_notify.
The shim layer is made possible by the addition of
zephyr/shim/include/i2c/i2c.h which adds a functions that
needs to be implemented per chip (npcx7 family in this case)
and allows us to map the current port int which is defined
in chip/${CHIP}/registers.h (chip/npcx/registers-npcx7.h in
our case). This function (i2c_get_device_for_port) maps the
platform/ec port int to a const struct device * which is
needed in the Zephyr I2C APIs.
BRANCH=none
BUG=b:171302975
TEST=clean_build.sh projects/experimental/volteer/ and make BOARD=eve
Signed-off-by: Yuval Peress <peress@chromium.org>
Change-Id: I210f4758337bf384d0d6f103eef8b89126887d11
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2504285
Reviewed-by: Simon Glass <sjg@chromium.org>
Commit-Queue: Simon Glass <sjg@chromium.org>
-rw-r--r-- | chip/npcx/registers-npcx7.h | 7 | ||||
-rw-r--r-- | common/i2c_master.c | 35 | ||||
-rw-r--r-- | zephyr/CMakeLists.txt | 3 | ||||
-rw-r--r-- | zephyr/Kconfig | 10 | ||||
-rw-r--r-- | zephyr/shim/CMakeLists.txt | 6 | ||||
-rw-r--r-- | zephyr/shim/chip/CMakeLists.txt | 35 | ||||
-rw-r--r-- | zephyr/shim/chip/npcx/CMakeLists.txt | 5 | ||||
-rw-r--r-- | zephyr/shim/chip/npcx/i2c.c | 44 | ||||
-rw-r--r-- | zephyr/shim/include/config_chip.h | 15 | ||||
-rw-r--r-- | zephyr/shim/include/i2c/i2c.h | 28 | ||||
-rw-r--r-- | zephyr/shim/src/CMakeLists.txt | 8 | ||||
-rw-r--r-- | zephyr/shim/src/i2c.c | 23 |
12 files changed, 206 insertions, 13 deletions
diff --git a/chip/npcx/registers-npcx7.h b/chip/npcx/registers-npcx7.h index 6fa10f5430..c496640c34 100644 --- a/chip/npcx/registers-npcx7.h +++ b/chip/npcx/registers-npcx7.h @@ -256,7 +256,12 @@ enum { #define NPCX_SMBSEL_SMB5SEL 5 #define NPCX_SMBSEL_SMB6SEL 6 -/* SMB enumeration: I2C port definitions. */ +/* + * SMB enumeration: I2C port definitions. + * + * Node: If making changes here please update the translation layer for Zephyr + * builds at zephyr/shim/chip/npcx/i2c.c. + */ enum { NPCX_I2C_PORT0_0 = 0, /* I2C port 0, bus 0 */ NPCX_I2C_PORT1_0, /* I2C port 1, bus 0 */ diff --git a/common/i2c_master.c b/common/i2c_master.c index ad6c50c215..23164720b5 100644 --- a/common/i2c_master.c +++ b/common/i2c_master.c @@ -23,6 +23,11 @@ #include "watchdog.h" #include "virtual_battery.h" +#ifdef CONFIG_ZEPHYR +#include <drivers/i2c.h> +#include "i2c/i2c.h" +#endif /* CONFIG_ZEPHYR */ + /* Delay for bitbanging i2c corresponds roughly to 100kHz. */ #define I2C_BITBANG_DELAY_US 5 @@ -43,12 +48,25 @@ #define I2C_BITBANG_PORT_COUNT 0 #endif -static struct mutex port_mutex[I2C_CONTROLLER_COUNT + I2C_BITBANG_PORT_COUNT]; +static mutex_t port_mutex[I2C_CONTROLLER_COUNT + I2C_BITBANG_PORT_COUNT]; /* A bitmap of the controllers which are currently servicing a request. */ static uint32_t i2c_port_active_list; BUILD_ASSERT(ARRAY_SIZE(port_mutex) < 32); static uint8_t port_protected[I2C_PORT_COUNT + I2C_BITBANG_PORT_COUNT]; +#ifdef CONFIG_ZEPHYR +static int init_port_mutex(const struct device *dev) +{ + ARG_UNUSED(dev); + + for (int i = 0; i < ARRAY_SIZE(port_mutex); ++i) + k_mutex_init(port_mutex + i); + + return 0; +} +SYS_INIT(init_port_mutex, POST_KERNEL, 50); +#endif /* CONFIG_ZEPHYR */ + /** * Non-deterministically test the lock status of the port. If another task * has locked the port and the caller is accessing it illegally, then this test @@ -68,7 +86,6 @@ static int i2c_port_is_locked(int port) return (i2c_port_active_list >> port) & 1; } - const struct i2c_port_t *get_i2c_port(const int port) { int i; @@ -89,10 +106,10 @@ const struct i2c_port_t *get_i2c_port(const int port) return NULL; } -static int chip_i2c_xfer_with_notify(const int port, - const uint16_t slave_addr_flags, - const uint8_t *out, int out_size, - uint8_t *in, int in_size, int flags) +__maybe_unused static int chip_i2c_xfer_with_notify( + const int port, const uint16_t slave_addr_flags, + const uint8_t *out, int out_size, + uint8_t *in, int in_size, int flags) { int ret; uint16_t addr_flags = slave_addr_flags; @@ -164,7 +181,6 @@ int i2c_xfer_unlocked(const int port, { int i; int ret = EC_SUCCESS; - uint16_t addr_flags = slave_addr_flags & ~I2C_FLAG_PEC; if (!i2c_port_is_locked(port)) { @@ -173,7 +189,10 @@ int i2c_xfer_unlocked(const int port, } for (i = 0; i <= CONFIG_I2C_NACK_RETRY_COUNT; i++) { -#ifdef CONFIG_I2C_XFER_LARGE_READ +#ifdef CONFIG_ZEPHYR + ret = i2c_write_read(i2c_get_device_for_port(port), addr_flags, + out, out_size, in, in_size); +#elif defined(CONFIG_I2C_XFER_LARGE_READ) ret = i2c_xfer_no_retry(port, addr_flags, out, out_size, in, in_size, flags); diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 49b08c16dd..7f7d5f4308 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -32,10 +32,11 @@ zephyr_include_directories_ifdef( "${PLATFORM_EC}/test" "${PLATFORM_EC}/include") -add_subdirectory_ifdef(CONFIG_PLATFORM_EC "shim/src") +add_subdirectory_ifdef(CONFIG_PLATFORM_EC "shim") zephyr_sources_ifdef(CONFIG_PLATFORM_EC "${PLATFORM_EC}/common/base32.c") zephyr_sources_ifdef(CONFIG_SHELL "${PLATFORM_EC}/common/gpio_commands.c") +zephyr_sources_ifdef(CONFIG_PLATFORM_EC_I2C "${PLATFORM_EC}/common/i2c_master.c") zephyr_sources_ifdef(CONFIG_PLATFORM_EC_KEYBOARD_PROTOCOL_8042 "${PLATFORM_EC}/common/keyboard_8042.c") zephyr_sources_ifdef(CONFIG_PLATFORM_EC_LID_SWITCH diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 827a3b1d70..6569450766 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -109,4 +109,14 @@ config PLATFORM_EC_LID_SWITCH commands in platform/ec. This requires a GPIO named GPIO_LID_OPEN to be defined in gpio_map.h. +config PLATFORM_EC_I2C + bool "Enable the EC i2c module" + default y + help + Enable compilation of the EC i2c module. Once enabled, it will be + possible to make calls using the old platform/ec i2c APIs defined + in include/i2c.h and implemented in common/i2c_master.c. Doing so + should make shimming other platform/ec modules which rely on i2c + communication "just work" without requiring any further code changes. + endif # PLATFORM_EC diff --git a/zephyr/shim/CMakeLists.txt b/zephyr/shim/CMakeLists.txt new file mode 100644 index 0000000000..3add679c23 --- /dev/null +++ b/zephyr/shim/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +add_subdirectory("src") +add_subdirectory("chip") diff --git a/zephyr/shim/chip/CMakeLists.txt b/zephyr/shim/chip/CMakeLists.txt new file mode 100644 index 0000000000..7a77febaa1 --- /dev/null +++ b/zephyr/shim/chip/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Translate Zephyr CONFIG_SOC_* values to platform/ec CHIP_* values. +if (DEFINED CONFIG_SOC_NPCX7M6FB) + set(CHIP_FAMILY "NPCX7") + set(CHIP_VARIANT "NPCX7M6FB") +endif() + +# Add compile definitions for CHIP_FAMILY_ and CHIP_VARIANT_, these are used +# through the platform/ec code and are often used to branch header definitions +# which are still being used. It is possible that eventually (when we also no +# longer require the platform/ec/chip/... headers) that we'll be able to get +# rid of this. +zephyr_compile_definitions("CHIP_FAMILY_${CHIP_FAMILY}") +zephyr_compile_definitions("CHIP_VARIANT_${CHIP_VARIANT}") + +if ("${CHIP_FAMILY}" MATCHES "^NPCX[0-9]$") + add_subdirectory(npcx) + zephyr_include_directories("${PLATFORM_EC}/chip/npcx") + string(TOLOWER "npcx/i2c-${CHIP_FAMILY}.c" chip_specific_i2c_impl) +endif() + +# Adding chip specific i2c implementation here. These contain the specific +# code used to implement generic information about platform/ec +# port numbers and their properties. As such they're basically the +# platform/ec's abstraction of devicetree and aren't worth replacing +# quite yet until a cleaner picture of how the full migration for i2c +# will be done. +if (DEFINED chip_specific_i2c_impl) + zephyr_sources_ifdef(CONFIG_PLATFORM_EC_I2C + "${PLATFORM_EC}/chip/${chip_specific_i2c_impl}") +endif() + diff --git a/zephyr/shim/chip/npcx/CMakeLists.txt b/zephyr/shim/chip/npcx/CMakeLists.txt new file mode 100644 index 0000000000..377cb652b4 --- /dev/null +++ b/zephyr/shim/chip/npcx/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +zephyr_sources(i2c.c) diff --git a/zephyr/shim/chip/npcx/i2c.c b/zephyr/shim/chip/npcx/i2c.c new file mode 100644 index 0000000000..1f6fe6336d --- /dev/null +++ b/zephyr/shim/chip/npcx/i2c.c @@ -0,0 +1,44 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <sys/util.h> + +#include "registers.h" +#include "i2c/i2c.h" + +/* Shorthand for getting the device binding for a given devicetree label. */ +#define BINDING_FOR(label) \ + device_get_binding( \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(label), okay), \ + (DT_LABEL(DT_NODELABEL(label))), (""))) + +static const struct device *i2c_devices[NPCX_I2C_COUNT]; + +static int init_device_bindings(const struct device *device) +{ + ARG_UNUSED(device); + i2c_devices[NPCX_I2C_PORT0_0] = BINDING_FOR(i2c0_0); + i2c_devices[NPCX_I2C_PORT1_0] = BINDING_FOR(i2c1_0); + i2c_devices[NPCX_I2C_PORT2_0] = BINDING_FOR(i2c2_0); + i2c_devices[NPCX_I2C_PORT3_0] = BINDING_FOR(i2c3_0); +#ifdef CHIP_VARIANT_NPCX7M6G + i2c_devices[NPCX_I2C_PORT4_0] = BINDING_FOR(i2c4_0); +#endif + i2c_devices[NPCX_I2C_PORT4_1] = BINDING_FOR(i2c4_1); + i2c_devices[NPCX_I2C_PORT5_0] = BINDING_FOR(i2c5_0); + i2c_devices[NPCX_I2C_PORT5_1] = BINDING_FOR(i2c5_1); + i2c_devices[NPCX_I2C_PORT6_0] = BINDING_FOR(i2c6_0); + i2c_devices[NPCX_I2C_PORT6_1] = BINDING_FOR(i2c6_1); + i2c_devices[NPCX_I2C_PORT7_0] = BINDING_FOR(i2c7_0); + return 0; +} +SYS_INIT(init_device_bindings, POST_KERNEL, 51); + +const struct device *i2c_get_device_for_port(const int port) +{ + if (port < 0 || port >= NPCX_I2C_COUNT) + return NULL; + return i2c_devices[port]; +} diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h index 511d934bc5..d767b5ad90 100644 --- a/zephyr/shim/include/config_chip.h +++ b/zephyr/shim/include/config_chip.h @@ -51,4 +51,19 @@ #endif /* CONFIG_PLATFORM_EC_TIMER */ +/* + * Load the chip family specific header. Normally for npcx, this would be done + * by chip/npcx/config_chip.h but since this file is replacing that header + * we'll need (for now) to load it ourselves. Long term, the functions, enums, + * and constants in this header will be replaced by more Zephyr/devicetree + * specific code. + */ +#ifdef CHIP_FAMILY_NPCX7 +#include "config_chip-npcx7.h" +#endif /* CHIP_FAMILY_NPCX7 */ + +#ifdef CONFIG_PLATFORM_EC_I2C +#define CONFIG_I2C +#endif /* CONFIG_PLATFORM_EC_I2C */ + #endif /* __CROS_EC_CONFIG_CHIP_H */ diff --git a/zephyr/shim/include/i2c/i2c.h b/zephyr/shim/include/i2c/i2c.h new file mode 100644 index 0000000000..289f8b753e --- /dev/null +++ b/zephyr/shim/include/i2c/i2c.h @@ -0,0 +1,28 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef ZEPHYR_CHROME_I2C_I2C_H +#define ZEPHYR_CHROME_I2C_I2C_H + +#include <device.h> +#include <devicetree.h> + +/** + * @brief Adaptation of platform/ec's port IDs which map a port/bus to a device. + * + * This function should be implemented per chip and should map the enum value + * defined for the chip for encoding each valid port/bus combination. For + * example, the npcx chip defines the port/bus combinations NPCX_I2C_PORT* under + * chip/npcx/registers-npcx7.h. + * + * Thus, the npcx shim should implement this function to map the enum values + * to the correct devicetree device. + * + * @param port The port to get the device for. + * @return Pointer to the device struct or {@code NULL} if none are available. + */ +const struct device *i2c_get_device_for_port(const int port); + +#endif /* ZEPHYR_CHROME_I2C_I2C_H */ diff --git a/zephyr/shim/src/CMakeLists.txt b/zephyr/shim/src/CMakeLists.txt index 3d7f4b3099..8273ba80a5 100644 --- a/zephyr/shim/src/CMakeLists.txt +++ b/zephyr/shim/src/CMakeLists.txt @@ -3,9 +3,11 @@ # found in the LICENSE file. zephyr_sources(console.c) -zephyr_sources(util.c) zephyr_sources(gpio.c) +zephyr_sources(util.c) + zephyr_sources_ifdef(CONFIG_PLATFORM_EC_HOOKS hooks.c) -zephyr_sources_ifdef(CONFIG_CROS_EC system.c) -zephyr_sources_ifdef(CONFIG_SHIMMED_TASKS tasks.c) zephyr_sources_ifdef(CONFIG_PLATFORM_EC_TIMER hwtimer.c) +zephyr_sources_ifdef(CONFIG_PLATFORM_EC_I2C i2c.c) +zephyr_sources_ifdef(CONFIG_CROS_EC system.c) +zephyr_sources_ifdef(CONFIG_SHIMMED_TASKS tasks.c) diff --git a/zephyr/shim/src/i2c.c b/zephyr/shim/src/i2c.c new file mode 100644 index 0000000000..4420cec41c --- /dev/null +++ b/zephyr/shim/src/i2c.c @@ -0,0 +1,23 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "i2c.h" +#include "i2c/i2c.h" + +/* + * Long term we will not need these, for now they're needed to get things to + * build since these extern symbols are usually defined in + * board/${BOARD}/board.c. + * + * Since all the ports will eventually be handled by device tree. This will + * be removed at that point. + */ +const struct i2c_port_t i2c_ports[] = {}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +int i2c_get_line_levels(int port) +{ + return I2C_LINE_IDLE; +} |