diff options
author | Dawid Niedzwiecki <dn@semihalf.com> | 2021-06-02 11:57:59 +0200 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-06-08 08:08:44 +0000 |
commit | a4dc0476c7b0955fbc8d0885a5d442bc41504db4 (patch) | |
tree | 4e7f65dab82c621dde80489e9cfc81d67ac0da63 | |
parent | d5e9773ea42c8ea3c2666b031abef85f3d43b162 (diff) | |
download | chrome-ec-a4dc0476c7b0955fbc8d0885a5d442bc41504db4.tar.gz |
zephyr: Fix I2C_PASSTHRU host command
ZephyrEC uses different I2C port numbers than CrosEC does, so convert
the received remote port via I2C_PASSTHRU command into a proper one.
The conversion is done based on a new property remote-port, which tells
what port number is used by external components like kernel.
The change fixes an issue with unexpected entering OTG mode by the
charger.
BUG=b:188885798
BRANCH=none
TEST=Flash Lazor and make sure that no "charge problem" prints are
displayed.
Signed-off-by: Dawid Niedzwiecki <dn@semihalf.com>
Change-Id: Id00265a3abf286ca59cbecb38ff7933d75e0d361
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2933296
Reviewed-by: Yuval Peress <peress@chromium.org>
-rw-r--r-- | common/i2c_controller.c | 38 | ||||
-rw-r--r-- | zephyr/dts/bindings/i2c/cros-ec-i2c-port-base.yaml | 6 | ||||
-rw-r--r-- | zephyr/projects/trogdor/boards/arm/trogdor/trogdor.dts | 1 | ||||
-rw-r--r-- | zephyr/shim/include/i2c/i2c.h | 12 | ||||
-rw-r--r-- | zephyr/shim/src/i2c.c | 16 |
5 files changed, 70 insertions, 3 deletions
diff --git a/common/i2c_controller.c b/common/i2c_controller.c index 035cf8d8ca..e2fa3ec28f 100644 --- a/common/i2c_controller.c +++ b/common/i2c_controller.c @@ -1159,8 +1159,32 @@ static int check_i2c_params(const struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } +#ifdef I2C_PORT_VIRTUAL_BATTERY +static inline int is_i2c_port_virtual_battery(int port) +{ +#ifdef CONFIG_ZEPHYR + /* For Zephyr compare the actual device, which will be used in + * i2c_transfer function. + */ + return (i2c_get_device_for_port(port) == + i2c_get_device_for_port(I2C_PORT_VIRTUAL_BATTERY)); +#else + return (port == I2C_PORT_VIRTUAL_BATTERY); +#endif +} +#endif /* I2C_PORT_VIRTUAL_BATTERY */ + static enum ec_status i2c_command_passthru(struct host_cmd_handler_args *args) { +#ifdef CONFIG_ZEPHYR + /* For Zephyr, convert the received remote port number to a port number + * used in EC. + */ + ((struct ec_params_i2c_passthru *)(args->params))->port = + i2c_get_port_from_remote_port( + ((struct ec_params_i2c_passthru *)(args->params)) + ->port); +#endif const struct ec_params_i2c_passthru *params = args->params; const struct ec_params_i2c_passthru_msg *msg; struct ec_response_i2c_passthru *resp = args->response; @@ -1220,9 +1244,8 @@ static enum ec_status i2c_command_passthru(struct host_cmd_handler_args *args) if (resp->num_msgs == params->num_msgs - 1) xferflags |= I2C_XFER_STOP; -#if defined(VIRTUAL_BATTERY_ADDR_FLAGS) && \ - (defined(CONFIG_ZEPHYR) || defined(I2C_PORT_VIRTUAL_BATTERY)) - if (params->port == I2C_PORT_VIRTUAL_BATTERY && +#if defined(VIRTUAL_BATTERY_ADDR_FLAGS) && defined(I2C_PORT_VIRTUAL_BATTERY) + if (is_i2c_port_virtual_battery(params->port) && addr_flags == VIRTUAL_BATTERY_ADDR_FLAGS) { if (virtual_battery_handler(resp, in_len, &rv, xferflags, read_len, @@ -1318,6 +1341,15 @@ static void i2c_passthru_protect_tcpc_ports(void) static enum ec_status i2c_command_passthru_protect(struct host_cmd_handler_args *args) { +#ifdef CONFIG_ZEPHYR + /* For Zephyr, convert the received remote port number to a port number + * used in EC. + */ + ((struct ec_params_i2c_passthru_protect *)(args->params)) + ->port = i2c_get_port_from_remote_port( + ((struct ec_params_i2c_passthru_protect *)(args->params)) + ->port); +#endif const struct ec_params_i2c_passthru_protect *params = args->params; struct ec_response_i2c_passthru_protect *resp = args->response; diff --git a/zephyr/dts/bindings/i2c/cros-ec-i2c-port-base.yaml b/zephyr/dts/bindings/i2c/cros-ec-i2c-port-base.yaml index d00e1346b8..7f7350b668 100644 --- a/zephyr/dts/bindings/i2c/cros-ec-i2c-port-base.yaml +++ b/zephyr/dts/bindings/i2c/cros-ec-i2c-port-base.yaml @@ -7,6 +7,12 @@ properties: i2c-port: type: phandle required: true + remote-port: + type: int + required: false + description: + A port number used by remote components like Kernel via the I2C_PASSTHRU + Host Command enum-name: type: string required: true diff --git a/zephyr/projects/trogdor/boards/arm/trogdor/trogdor.dts b/zephyr/projects/trogdor/boards/arm/trogdor/trogdor.dts index 7e3100a0fe..e2d57af8fc 100644 --- a/zephyr/projects/trogdor/boards/arm/trogdor/trogdor.dts +++ b/zephyr/projects/trogdor/boards/arm/trogdor/trogdor.dts @@ -40,6 +40,7 @@ }; battery { i2c-port = <&i2c0_0>; + remote-port = <0>; enum-name = "I2C_PORT_BATTERY"; label = "BATTERY"; }; diff --git a/zephyr/shim/include/i2c/i2c.h b/zephyr/shim/include/i2c/i2c.h index 930a6447a1..f227da48b1 100644 --- a/zephyr/shim/include/i2c/i2c.h +++ b/zephyr/shim/include/i2c/i2c.h @@ -39,4 +39,16 @@ enum i2c_ports { */ const struct device *i2c_get_device_for_port(const int port); +/** + * @brief Get a port number for a received remote port number. + * + * This function translate a received port number via the I2C_PASSTHRU host + * command to a port number used in ZephyrEC based on remote_port property in + * dts. The first port which matches the remote port number is returned. + * + * @param port The received remote port. + * @return Port number used in EC. -1 if the remote port is not defined + */ +int i2c_get_port_from_remote_port(int remote_port); + #endif /* ZEPHYR_CHROME_I2C_I2C_H */ diff --git a/zephyr/shim/src/i2c.c b/zephyr/shim/src/i2c.c index b3b2117b98..7c6ffa765b 100644 --- a/zephyr/shim/src/i2c.c +++ b/zephyr/shim/src/i2c.c @@ -16,6 +16,9 @@ i2c_devices[I2C_PORT(id)] = device_get_binding( \ DT_PROP_BY_PHANDLE(id, i2c_port, label)); +#define INIT_REMOTE_PORTS(id) \ + i2c_remote_ports[I2C_PORT(id)] = DT_PROP_OR(id, remote_port, -1); + #define I2C_CONFIG_GPIO(id, type) \ DT_ENUM_UPPER_TOKEN(DT_CHILD(DT_CHILD(id, config), type), enum_name) @@ -38,6 +41,7 @@ const struct i2c_port_t i2c_ports[] = { #endif }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +static int i2c_remote_ports[I2C_PORT_COUNT]; int i2c_get_line_levels(int port) { @@ -50,6 +54,7 @@ static int init_device_bindings(const struct device *device) { ARG_UNUSED(device); DT_FOREACH_CHILD(DT_PATH(named_i2c_ports), INIT_DEV_BINDING) + DT_FOREACH_CHILD(DT_PATH(named_i2c_ports), INIT_REMOTE_PORTS) return 0; } SYS_INIT(init_device_bindings, POST_KERNEL, 51); @@ -60,3 +65,14 @@ const struct device *i2c_get_device_for_port(const int port) return NULL; return i2c_devices[port]; } + +int i2c_get_port_from_remote_port(int remote_port) +{ + for (int port = 0; port < I2C_PORT_COUNT; port++) { + if (i2c_remote_ports[port] == remote_port) + return port; + } + + /* Remote port is not defined, return -1 to signal the problem */ + return -1; +} |