summaryrefslogtreecommitdiff
path: root/zephyr/shim/include/usbc/usb_muxes.h
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/shim/include/usbc/usb_muxes.h')
-rw-r--r--zephyr/shim/include/usbc/usb_muxes.h441
1 files changed, 266 insertions, 175 deletions
diff --git a/zephyr/shim/include/usbc/usb_muxes.h b/zephyr/shim/include/usbc/usb_muxes.h
index f7cfd7159b..9dce1a3aa5 100644
--- a/zephyr/shim/include/usbc/usb_muxes.h
+++ b/zephyr/shim/include/usbc/usb_muxes.h
@@ -1,4 +1,4 @@
-/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+/* 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.
*/
@@ -16,6 +16,7 @@
#include "usbc/ps8743_usb_mux.h"
#include "usbc/tcpci_usb_mux.h"
#include "usbc/tusb1064_usb_mux.h"
+#include "usbc/utils.h"
#include "usbc/virtual_usb_mux.h"
/**
@@ -48,15 +49,28 @@
#define USB_MUX_DRIVER_GET_CONFIG(driver) GET_ARG_N(2, __DEBRACKET driver)
/**
- * @brief USB mux port number based on parent node in DTS
+ * @brief Name of USB mux chain structure for given port and place in chain.
+ * Note, that root of chain is not referred by this name, but
+ * usb_muxes[@p port_id].
*
- * @param port_id USBC node ID
+ * @param idx Place in chain
+ * @param port_id USBC port id
*/
-#define USB_MUX_PORT(port_id) DT_REG_ADDR(port_id)
+#define USB_MUX_CHAIN_STRUCT_NAME(idx, port_id) \
+ DT_CAT4(USB_MUX_chain_port_, port_id, _mux_, idx)
/**
- * @brief Name of USB mux structure if node is not EMPTY. Note, that root of
- * chain is not referred by this name, but usb_muxes[USB_MUX_PORT(id)].
+ * @brief Declaration of USB mux chain structure for @p idx mux in @p port_id
+ * USB-C port's chain
+ *
+ * @param port_id USBC port ID (number)
+ * @param idx Place in chain
+ */
+#define USB_MUX_CHAIN_STRUCT_DECLARE(port_id, idx) \
+ MAYBE_CONST struct usb_mux_chain USB_MUX_CHAIN_STRUCT_NAME(idx, port_id)
+
+/**
+ * @brief Name of USB mux structure if node @p mux_id is not EMPTY.
*
* @param mux_id USB mux node ID
*/
@@ -82,22 +96,16 @@
* @brief Declaration of USB mux board_init function
*
* @param mux_id USB mux node ID
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
- * @param conf Driver configuration function
*/
-#define USB_MUX_CB_BOARD_INIT_DECLARE(mux_id, port_id, idx, conf) \
+#define USB_MUX_CB_BOARD_INIT_DECLARE(mux_id) \
int DT_STRING_TOKEN(mux_id, board_init)(const struct usb_mux *);
/**
* @brief Declaration of USB mux board_set function
*
* @param mux_id USB mux node ID
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
- * @param conf Driver configuration function
*/
-#define USB_MUX_CB_BOARD_SET_DECLARE(mux_id, port_id, idx, conf) \
+#define USB_MUX_CB_BOARD_SET_DECLARE(mux_id) \
int DT_STRING_TOKEN(mux_id, board_set)(const struct usb_mux *, \
mux_state_t);
@@ -112,33 +120,43 @@
/**
* @brief Get node id of @p idx USB mux in chain
*
+ * @param chain_id USB mux chain node ID
* @param idx Position of USB mux in chain
- * @param port_id USBC node ID
*/
-#define USB_MUX_GET_CHAIN_N(idx, port_id) \
- DT_PHANDLE_BY_IDX(port_id, usb_muxes, idx)
+#define USB_MUX_GET_CHAIN_N(chain_id, idx) \
+ DT_PHANDLE_BY_IDX(chain_id, usb_muxes, idx)
/**
- * @brief Get node id of next USB mux in chain or EMPTY if it is last mux
+ * @brief Get next USB mux chain structure name or EMPTY if it is last mux
*
- * @param port_id USBC node ID
+ * @param chain_id USB mux chain node ID
* @param idx Position of USB mux in chain
*/
-#define USB_MUX_NEXT(port_id, idx) \
- GET_ARG_N(2, \
- GET_ARGS_LESS_N( \
- idx, LISTIFY(DT_PROP_LEN(port_id, usb_muxes), \
- USB_MUX_GET_CHAIN_N, (, ), port_id)), \
+#define USB_MUX_CHAIN_NEXT_NAME(chain_id, idx) \
+ GET_ARG_N(2, \
+ GET_ARGS_LESS_N(idx, \
+ LISTIFY(DT_PROP_LEN(chain_id, usb_muxes), \
+ USB_MUX_CHAIN_STRUCT_NAME, (, ), \
+ USBC_PORT(chain_id))), \
EMPTY)
/**
* @brief Get pointer to next USB mux in chain or NULL if it is last mux
*
- * @param port_id USBC node ID
+ * @param chain_id USB mux chain node ID
+ * @param idx Position of USB mux in chain
+ */
+#define USB_MUX_CHAIN_NEXT_POINTER(chain_id, idx) \
+ USB_MUX_POINTER_OR_NULL(USB_MUX_CHAIN_NEXT_NAME(chain_id, idx))
+
+/**
+ * @brief Get pointer to USB mux that is @p idx in chain @p chain_id
+ *
+ * @param chain_id USB mux chain node ID
* @param idx Position of USB mux in chain
*/
-#define USB_MUX_NEXT_POINTER(port_id, idx) \
- USB_MUX_POINTER_OR_NULL(USB_MUX_STRUCT_NAME(USB_MUX_NEXT(port_id, idx)))
+#define USB_MUX_POINTER(chain_id, idx) \
+ &USB_MUX_STRUCT_NAME(USB_MUX_GET_CHAIN_N(chain_id, idx))
/**
* @brief Generate pointer to function from @p cb_name property or NULL
@@ -154,255 +172,328 @@
* @brief Set struct usb_mux fields common for all USB muxes and alter flags
*
* @param mux_id USB mux node ID
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
* @param flags_mask Mask for bits that should be igonred in flags property
* @param flags_val Value that should be used instead for masked bits
*/
-#define USB_MUX_COMMON_FIELDS_WITH_FLAGS(mux_id, port_id, idx, flags_mask, \
- flags_val) \
- .usb_port = USB_MUX_PORT(port_id), \
- .next_mux = USB_MUX_NEXT_POINTER(port_id, idx), \
- .board_init = USB_MUX_CALLBACK_OR_NULL(mux_id, board_init), \
- .board_set = USB_MUX_CALLBACK_OR_NULL(mux_id, board_set), \
+#define USB_MUX_COMMON_FIELDS_WITH_FLAGS(mux_id, flags_mask, flags_val) \
+ .usb_port = USB_MUX_PORT(mux_id), \
+ .board_init = USB_MUX_CALLBACK_OR_NULL(mux_id, board_init), \
+ .board_set = USB_MUX_CALLBACK_OR_NULL(mux_id, board_set), \
.flags = (DT_PROP(mux_id, flags) & ~(flags_mask)) | (flags_val)
/**
* @brief Set struct usb_mux fields common for all USB muxes
*
* @param mux_id USB mux node ID
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
*/
-#define USB_MUX_COMMON_FIELDS(mux_id, port_id, idx) \
- USB_MUX_COMMON_FIELDS_WITH_FLAGS(mux_id, port_id, idx, 0, 0)
+#define USB_MUX_COMMON_FIELDS(mux_id) \
+ USB_MUX_COMMON_FIELDS_WITH_FLAGS(mux_id, 0, 0)
/**
- * @brief Expands to 1 if @p mux_id has @p compat compatible. It is required
- * to makes sure that @p compat is expanded before DT_NODE_HAS_COMPAT
+ * @brief Declare USB mux structure
*
* @param mux_id USB mux node ID
- * @param compat USB mux driver compatible
+ * @param conf Driver configuration function
*/
-#define USB_MUX_IS_COMPATIBLE(mux_id, compat) DT_NODE_HAS_COMPAT(mux_id, compat)
+#define USB_MUX_DECLARE(mux_id, conf) extern USB_MUX_STRUCT_DECLARE(mux_id);
/**
- * @brief Expands to @p driver config if @p mux_id is compatible with @p driver
+ * @brief Define USB mux structure using driver USB_MUX_CONFIG_* macro
*
- * @param driver USB mux driver description in format (compatible, config)
* @param mux_id USB mux node ID
+ * @param conf Driver configuration function
*/
-#define USB_MUX_DRIVER_CONFIG_IF_COMPAT(driver, mux_id) \
- COND_CODE_1(USB_MUX_IS_COMPATIBLE(mux_id, \
- USB_MUX_DRIVER_GET_COMPAT(driver)), \
- (USB_MUX_DRIVER_GET_CONFIG(driver)), ())
+#define USB_MUX_DEFINE(mux_id, conf) \
+ USB_MUX_STRUCT_DECLARE(mux_id) = conf(mux_id);
/**
- * @brief Find driver from USB_MUX_DRIVERS that is compatible with @p mux_id
+ * @brief Call @p cb_op if @p mux_id has @p cb_prop property
*
* @param mux_id USB mux node ID
+ * @param cb_prop The callback property name
+ * @param cb_op Operation to perform on USB muxes
*/
-#define USB_MUX_FIND_DRIVER_CONFIG(mux_id) \
- FOR_EACH_FIXED_ARG(USB_MUX_DRIVER_CONFIG_IF_COMPAT, (), mux_id, \
- USB_MUX_DRIVERS)
+#define USB_MUX_CB_DECLARE_IF_EXIST(mux_id, cb_prop, cb_op) \
+ COND_CODE_1(DT_NODE_HAS_PROP(mux_id, cb_prop), (cb_op(mux_id)), ())
/**
- * @brief Get driver configuration macro for @p mux_id and call @p op
+ * @brief Declare USB mux board_set function @p mux_id has board_set property
*
* @param mux_id USB mux node ID
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
- * @param op Operation to perform on USB muxes
+ * @param conf Driver configuration function
*/
-#define USB_MUX_CALL_OP(mux_id, port_id, idx, op) \
- op(mux_id, port_id, idx, USB_MUX_FIND_DRIVER_CONFIG(mux_id))
+#define USB_MUX_CB_BOARD_SET_DECLARE_IF_EXISTS(mux_id, conf) \
+ USB_MUX_CB_DECLARE_IF_EXIST(mux_id, board_set, \
+ USB_MUX_CB_BOARD_SET_DECLARE)
/**
- * @brief Get USB mux node ID and call USB_MUX_CALL_OP
+ * @brief Declare USB mux board_init function @p mux_id has board_init property
*
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
- * @param op Operation to perform on USB muxes
+ * @param mux_id USB mux node ID
+ * @param conf Driver configuration function
*/
-#define USB_MUX_DO(port_id, idx, op) \
- USB_MUX_CALL_OP(USB_MUX_GET_CHAIN_N(idx, port_id), port_id, idx, op)
+#define USB_MUX_CB_BOARD_INIT_DECLARE_IF_EXISTS(mux_id, conf) \
+ USB_MUX_CB_DECLARE_IF_EXIST(mux_id, board_init, \
+ USB_MUX_CB_BOARD_INIT_DECLARE)
/**
- * @brief Declare USB mux structure
+ * @brief Call @p op operation for each node that is compatible with @p driver
*
- * @param mux_id USB mux node ID
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
- * @param conf Driver configuration function
+ * @param driver USB mux driver description in format (compatible, config)
+ * @param op Operation to perform on each USB mux. Should accept mux node ID and
+ * driver config as arguments.
*/
-#define USB_MUX_DECLARE(mux_id, port_id, idx, conf) \
- extern USB_MUX_STRUCT_DECLARE(mux_id);
+#define USB_MUX_DRIVER_CONFIG(driver, op) \
+ DT_FOREACH_STATUS_OKAY_VARGS(USB_MUX_DRIVER_GET_COMPAT(driver), op, \
+ USB_MUX_DRIVER_GET_CONFIG(driver))
/**
- * @brief Define USB mux structure using driver USB_MUX_CONFIG_* macro
+ * @brief Call @p op operation for each USB mux node that is compatible with
+ * any driver from the USB_MUX_DRIVERS list.
+ * DT_FOREACH_STATUS_OKAY_VARGS() macro can not be used in @p op
*
- * @param mux_id USB mux node ID
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
- * @param conf Driver configuration function
+ * @param op Operation to perform on each USB mux. Should accept mux node ID and
+ * driver config as arguments.
*/
-#define USB_MUX_DEFINE(mux_id, port_id, idx, conf) \
- USB_MUX_STRUCT_DECLARE(mux_id) = conf(mux_id, port_id, idx);
+#define USB_MUX_FOREACH_MUX_DT_VARGS(op) \
+ FOR_EACH_FIXED_ARG(USB_MUX_DRIVER_CONFIG, (), op, USB_MUX_DRIVERS)
/**
- * @brief Define entry of usb_muxes array using driver USB_MUX_CONFIG_* macro
+ * @brief Convert @p mux_id and @p conf pair into USB_MUX_LIST entry
*
* @param mux_id USB mux node ID
- * @param port_id USBC node ID
- * @param idx Position of USB mux in chain
* @param conf Driver configuration function
*/
-#define USB_MUX_ARRAY(mux_id, port_id, idx, conf) \
- [USB_MUX_PORT(port_id)] = conf(mux_id, port_id, idx),
+#define USB_MUX_TO_LIST(mux_id, conf) , (mux_id, conf)
+
+/**
+ * @brief List of all USB muxes with config matched by compatible. List is in
+ * format (mux1_id, conf1) , (mux2_id, conf2) ...
+ */
+#define USB_MUX_LIST \
+ LIST_DROP_EMPTY(USB_MUX_FOREACH_MUX_DT_VARGS(USB_MUX_TO_LIST))
/**
- * @brief Call @p op with first mux in chain
+ * @brief Call @p op with @p args arguments
*
- * @param port_id USBC node ID
- * @param op Operation to perform on USB mux first in chain. Needs to accept
- * USB mux node ID, USBC port node ID, position in chain, and driver
- * config as arguments.
+ * @param op Operation to perform on USB mux. Should accept mux node ID and
+ * driver config as arguments.
+ * @param args Arguments for @p op. Should be in format (mux_id, conf).
*/
-#define USB_MUX_FIRST(port_id, op) USB_MUX_DO(port_id, 0, op)
+#define USB_MUX_CALL_OP(args, op) op args
/**
- * @brief Call USB_MUX_DO if @p idx is not 0 (is not first mux in chain)
+ * @brief Call @p op operation for each USB mux node from USB_MUX_LIST. This is
+ * like USB_MUX_FOREACH_MUX_DT_VARGS(), except
+ * DT_FOREACH_STATUS_OKAY_VARGS() macro can be used in @p op
*
- * @param port_id USBC node ID
+ * @param op Operation to perform on each USB mux. Should accept mux node ID and
+ * driver config as arguments.
+ */
+#define USB_MUX_FOREACH_MUX(op) \
+ COND_CODE_0( \
+ IS_EMPTY(USB_MUX_LIST), \
+ (FOR_EACH_FIXED_ARG(USB_MUX_CALL_OP, (), op, USB_MUX_LIST)), \
+ (EMPTY))
+
+/**
+ * @brief Initialise chain structure for @p idx mux
+ *
+ * @param chain_id Chain DTS node ID
+ * @param idx USB mux index
+ */
+#define USB_MUX_CHAIN_STRUCT_INIT(chain_id, idx) \
+ { \
+ .mux = USB_MUX_POINTER(chain_id, idx), \
+ .next = USB_MUX_CHAIN_NEXT_POINTER(chain_id, idx), \
+ }
+
+/**
+ * @brief Helper macro to set chain structure value for @p idx mux
+ *
+ * @param chain_id Chain DTS node ID
+ * @param idx USB mux index
+ */
+#define USB_MUX_CHAIN_STRUCT_SET(chain_id, idx) \
+ (struct usb_mux_chain) USB_MUX_CHAIN_STRUCT_INIT(chain_id, idx)
+
+/**
+ * @brief Declaration of USB mux chain extern structure for @p idx mux in
+ * @p chain_id chain
+ *
+ * @param chain_id USB mux chain node ID
+ * @param idx Place in chain
+ */
+#define USB_MUX_CHAIN_STRUCT_DECLARE_EXTERN_OP(chain_id, idx) \
+ extern USB_MUX_CHAIN_STRUCT_DECLARE(USBC_PORT(chain_id), idx);
+
+/**
+ * @brief Declaration of USB mux chain structure for @p idx mux in @p chain_id
+ * chain
+ *
+ * @param chain_id USB mux chain node ID
+ * @param idx Place in chain
+ */
+#define USB_MUX_CHAIN_STRUCT_DECLARE_OP(chain_id, idx) \
+ USB_MUX_CHAIN_STRUCT_DECLARE(USBC_PORT(chain_id), idx);
+
+/**
+ * @brief Definition of USB mux chain structure for @p idx mux in @p chain_id
+ * chain
+ *
+ * @param chain_id USB mux chain node ID
+ * @param idx Place in chain
+ */
+#define USB_MUX_CHAIN_STRUCT_DEFINE_OP(chain_id, idx) \
+ USB_MUX_CHAIN_STRUCT_DECLARE(USBC_PORT(chain_id), idx) = \
+ USB_MUX_CHAIN_STRUCT_INIT(chain_id, idx);
+
+/**
+ * @brief Call @p op if @p idx is not 0 (is not the root mux of chain)
+ *
+ * @param chain_id Chain DTS node ID
* @param unused2 This argument is expected by DT_FOREACH_PROP_ELEM_VARGS
* @param idx Position of USB mux in chain
* @param op Operation to perform on USB muxes
*/
-#define USB_MUX_DO_SKIP_FIRST(port_id, unused2, idx, op) \
- COND_CODE_1(UTIL_BOOL(idx), (USB_MUX_DO(port_id, idx, op)), ())
+#define USB_MUX_SKIP_ROOT(chain_id, unused2, idx, op) \
+ COND_CODE_1(UTIL_BOOL(idx), (op(chain_id, idx)), ())
/**
- * @brief Call @p op with every mux in chain expect the first one
+ * @brief Call @p op for each mux in @p chain_id chain except the root mux
*
- * @param port_id USBC node ID
- * @param op Operation to perform on USB muxes. Needs to accept USB mux node
- * ID, USBC port node ID, position in chain, and driver config as
- * arguments.
+ * @param chain_id Chain DTS node ID
+ * @param op Operation to perform on USB muxes
*/
-#define USB_MUX_NO_FIRST(port_id, op) \
- DT_FOREACH_PROP_ELEM_VARGS(port_id, usb_muxes, USB_MUX_DO_SKIP_FIRST, \
- op)
+#define USB_MUX_FOREACH_NO_ROOT_MUX(chain_id, op) \
+ DT_FOREACH_PROP_ELEM_VARGS(chain_id, usb_muxes, USB_MUX_SKIP_ROOT, op)
/**
- * @brief Call USB_MUX_DO if @p cb is not empty
+ * @brief Create usb_muxes array entry for @p chain_id chain
*
- * @param port_id USBC node ID
- * @param mux_id USB mux node ID
- * @param idx Position of USB mux in chain
- * @param cb The callback name
- * @param op Operation to perform on USB muxes
+ * @param chain_id Chain DTS node ID
*/
-#define USB_MUX_DO_SKIP_NO_CB(port_id, mux_id, idx, cb, op) \
- COND_CODE_0(IS_EMPTY(DT_STRING_TOKEN(mux_id, cb)), \
- (USB_MUX_DO(port_id, idx, op)), ())
+#define USB_MUX_DEFINE_ROOT_MUX(chain_id) \
+ [USBC_PORT(chain_id)] = USB_MUX_CHAIN_STRUCT_INIT(chain_id, 0),
/**
- * @brief If usb_muxes property of @p port_id has callback property @p cb
+ * @brief Call @p op only if chain @p chain_id is not alternative
*
- * @param port_id USBC node ID
- * @param cb The callback name
- * @param op Operation to perform on USB muxes. Needs to accept USB mux node
- * ID, USBC port node ID, position in chain, and driver config as
- * arguments.
+ * @param chain_id Chain DTS node ID
+ * @param op Operation to perform on main USB mux chain
+ * @param ... Arguments to pass to the @p op operation
*/
-#define USB_MUX_HAS_CB(port_id, cb, op) \
- DT_FOREACH_PROP_ELEM_VARGS(port_id, usb_muxes, USB_MUX_DO_SKIP_NO_CB, \
- cb, op)
+#define USB_MUX_FOR_MAIN_CHAIN(chain_id, op, ...) \
+ COND_CODE_0(DT_PROP(chain_id, alternative_chain), \
+ (op(chain_id, ##__VA_ARGS__)), ())
/**
- * @brief If usb_muxes property of @p port_id has callback board_init
+ * @brief Call @p op for each USB mux chain
*
- * @param port_id USBC node ID
- * @param op Operation to perform on USB muxes. Needs to accept USB mux node
- * ID, USBC port node ID, position in chain, and driver config as
- * arguments.
+ * @param op Operation to perform on USB mux chain
*/
-#define USB_MUX_HAS_CB_BOARD_INIT(port_id, op) \
- USB_MUX_HAS_CB(port_id, board_init, op)
+#define USB_MUX_FOREACH_CHAIN(op) \
+ DT_FOREACH_STATUS_OKAY(cros_ec_usb_mux_chain, op)
/**
- * @brief If usb_muxes property of @p port_id has callback board_set
+ * @brief Call @p op for each USB mux chain with arguments
*
- * @param port_id USBC node ID
- * @param op Operation to perform on USB muxes. Needs to accept USB mux node
- * ID, USBC port node ID, position in chain, and driver config as
- * arguments.
+ * @param op Operation to perform on USB mux chain
+ * @param ... Arguments to pass to the @p op operation
*/
-#define USB_MUX_HAS_CB_BOARD_SET(port_id, op) \
- USB_MUX_HAS_CB(port_id, board_set, op)
+#define USB_MUX_FOREACH_CHAIN_VARGS(op, ...) \
+ DT_FOREACH_STATUS_OKAY_VARGS(cros_ec_usb_mux_chain, op, __VA_ARGS__)
/**
- * @brief Call @p op if @p idx mux in chain has BB retimer compatible
+ * @brief Construct first half of conditional expression (?:) that evaluates to
+ * @p chain_id USB port if @p idx mux in @p chain_id is the same as
+ * @p mux_id
*
- * @param port_id USBC node ID
+ * @param chain_id USB mux chain node ID
* @param unused2 This argument is expected by DT_FOREACH_PROP_ELEM_VARGS
* @param idx Position of USB mux in chain
- * @param op Operation to perform on BB retimer
+ * @param mux_id USB mux node ID to compare with @p idx mux
*/
-#define USB_MUX_ONLY_BB_RETIMER(port_id, unused2, idx, op) \
- COND_CODE_1(USB_MUX_IS_COMPATIBLE(USB_MUX_GET_CHAIN_N(idx, port_id), \
- BB_RETIMER_USB_MUX_COMPAT), \
- (op(USB_MUX_GET_CHAIN_N(idx, port_id), port_id, idx, \
- BB_RETIMER_CONTROLS_CONFIG)), \
- ())
+#define USB_MUX_PORT_IF_SAME_NODES(chain_id, unused2, idx, mux_id) \
+ DT_SAME_NODE(mux_id, USB_MUX_GET_CHAIN_N(chain_id, idx)) ? \
+ USBC_PORT(chain_id):
/**
- * @brief Call @p op with every BB retimer in chain
+ * @brief Compare @p mux_id with all muxes in @p chain_id
*
- * @param port_id USBC node ID
- * @param op Operation to perform on BB retimers. Needs to accept USB mux node
- * ID, USBC port node ID, position in chain, and driver config as
- * arguments.
+ * @param chain_id USB mux chain node ID
+ * @param mux_id USB mux node ID
*/
-#define USB_MUX_BB_RETIMERS(port_id, op) \
- DT_FOREACH_PROP_ELEM_VARGS(port_id, usb_muxes, \
- USB_MUX_ONLY_BB_RETIMER, op)
+#define USB_MUX_FIND_PORT(chain_id, mux_id) \
+ DT_FOREACH_PROP_ELEM_VARGS(chain_id, usb_muxes, \
+ USB_MUX_PORT_IF_SAME_NODES, mux_id)
+
+/**
+ * @brief Get port for @p mux_id by looking for an usb mux chain where @p mux_id
+ * is present. If the mux is not present in any chain, this macro
+ * evaluate to -1.
+ *
+ * This expands to:
+ * (DT_DEP_ORD(mux_id) == DT_DEP_ORD(USB_MUX_GET_CHAIN_N(chain1_id, 0))) ?
+ * USBC_PORT(chain1_id) :
+ * (DT_DEP_ORD(mux_id) == DT_DEP_ORD(USB_MUX_GET_CHAIN_N(chain1_id, 1))) ?
+ * USBC_PORT(chain1_id) :
+ * ...
+ * (DT_DEP_ORD(mux_id) == DT_DEP_ORD(USB_MUX_GET_CHAIN_N(chain1_id, n))) ?
+ * USBC_PORT(chain1_id) :
+ * (DT_DEP_ORD(mux_id) == DT_DEP_ORD(USB_MUX_GET_CHAIN_N(chain2_id, 0))) ?
+ * USBC_PORT(chain2_id) :
+ * ...
+ * (DT_DEP_ORD(mux_id) == DT_DEP_ORD(USB_MUX_GET_CHAIN_N(chainm_id, k))) ?
+ * USBC_PORT(chainm_id) : (-1)
+ *
+ * @param mux_id USB mux node ID
+ */
+#define USB_MUX_PORT(mux_id) \
+ (USB_MUX_FOREACH_CHAIN_VARGS(USB_MUX_FIND_PORT, mux_id)(-1))
/**
- * @brief If @p port_id has usb_muxes property, call @p op with every mux in
- * chain that passes @p filter
+ * @brief Set usb_mux_chain structure for mux @p idx in chain @p chain_id
*
- * @param port_id USBC node ID
- * @param filter Macro that should filter USB muxes and call @p op on them.
- * It has @p port_id and @p op as arguments. It is called
- * only for @p port_id that has usb_muxes property.
- * @param op Operation to perform on USB muxes. Needs to accept USB mux node
- * ID, USBC port node ID, position in chain, and driver config as
- * arguments.
+ * @param chain_id Alternative USB mux chain node ID
+ * @param idx Position of the mux in chain
*/
-#define USB_MUX_USBC_PORT_HAS_MUXES(port_id, filter, op) \
- COND_CODE_1(DT_NODE_HAS_PROP(port_id, usb_muxes), \
- (filter(port_id, op)), ())
+#define USB_MUX_SET_ALTERNATIVE(chain_id, idx) \
+ USB_MUX_CHAIN_STRUCT_NAME(idx, USBC_PORT(chain_id)) = \
+ USB_MUX_CHAIN_STRUCT_SET(chain_id, idx);
/**
- * @brief For every USBC port that has muxes, call @p op with every mux in chain
- * that passes @p filter
+ * @brief Enable alternative USB mux chain
*
- * @param filter Macro that should filter USB muxes and call @p op on them.
- * It has USBC port node ID and @p op as arguments. It is called
- * only for USBC ports that have usb_muxes property.
- * @param op Operation to perform on USB muxes. Needs to accept USB mux node
- * ID, USBC port node ID, position in chain, and driver config as
- * arguments.
+ * @param chain_id Alternative USB mux chain node ID
*/
-#define USB_MUX_FOREACH_USBC_PORT(filter, op) \
- DT_FOREACH_STATUS_OKAY_VARGS(named_usbc_port, \
- USB_MUX_USBC_PORT_HAS_MUXES, filter, op)
+#define USB_MUX_ENABLE_ALTERNATIVE_NODE(chain_id) \
+ do { \
+ usb_muxes[USBC_PORT(chain_id)] = \
+ USB_MUX_CHAIN_STRUCT_SET(chain_id, 0); \
+ USB_MUX_FOREACH_NO_ROOT_MUX(chain_id, USB_MUX_SET_ALTERNATIVE) \
+ } while (0)
+
+/**
+ * @brief Enable alternative USB mux chain
+ *
+ * @param nodelabel Label of alternative USB mux chain
+ */
+#define USB_MUX_ENABLE_ALTERNATIVE(nodelabel) \
+ USB_MUX_ENABLE_ALTERNATIVE_NODE(DT_NODELABEL(nodelabel))
/**
* Forward declare all usb_mux structures e.g.
* MAYBE_CONST struct usb_mux USB_MUX_NODE_<node_id>;
*/
-USB_MUX_FOREACH_USBC_PORT(USB_MUX_NO_FIRST, USB_MUX_DECLARE)
+USB_MUX_FOREACH_MUX(USB_MUX_DECLARE)
+
+/**
+ * Forward declare all usb_mux_chain structures e.g.
+ * extern MAYBE_CONST struct usb_mux_chain
+ * USB_MUX_chain_port_<node_id>_mux_<position_id>;
+ */
+USB_MUX_FOREACH_CHAIN_VARGS(USB_MUX_FOREACH_NO_ROOT_MUX,
+ USB_MUX_CHAIN_STRUCT_DECLARE_EXTERN_OP)
#endif /* ZEPHYR_CHROME_USBC_USB_MUXES_H */