diff options
-rw-r--r-- | zephyr/dts/bindings/usbc/cros-ec,usb-mux-chain.yaml | 19 | ||||
-rw-r--r-- | zephyr/shim/include/usbc/usb_muxes.h | 64 | ||||
-rw-r--r-- | zephyr/shim/src/usb_muxes.c | 16 |
3 files changed, 91 insertions, 8 deletions
diff --git a/zephyr/dts/bindings/usbc/cros-ec,usb-mux-chain.yaml b/zephyr/dts/bindings/usbc/cros-ec,usb-mux-chain.yaml index b0af5f6ce2..398d7255ac 100644 --- a/zephyr/dts/bindings/usbc/cros-ec,usb-mux-chain.yaml +++ b/zephyr/dts/bindings/usbc/cros-ec,usb-mux-chain.yaml @@ -17,8 +17,16 @@ properties: adding the "cros-ec,usb-mux-chain" as a child of the "named-usbc-port" node. -# Example DTS defining USB-C port 0 with usb mux chain. The chain has two muxes: -# BB retimer and virtual mux. + alternative-chain: + type: boolean + description: | + Set if this is alternative USB-C muxes chain. It can be selected in + runtime using USB_MUX_ENABLE_ALTERNATIVE macro. + +# Example DTS defining USB-C port 0 with main and alternative usb mux chains. +# The main chain has two muxes: BB retimer and virtual mux. +# The alternative chain has three muxes: BB retimer, SOC side BB retimer and +# virtual mux. # # usbc_port0: port0@0 { # compatible = "named-usbc-port"; @@ -29,4 +37,11 @@ properties: # usb-muxes = <&usb_c0_bb_retimer # &virtual_mux_c0>; # }; +# usb-mux-chain-0 { +# compatible = "cros-ec,usb-mux-chain"; +# alternative-chain; +# usb-muxes = <&usb_c0_bb_retimer +# &usb_c0_soc_side_bb_retimer +# &virtual_mux_c0>; +# }; # }; diff --git a/zephyr/shim/include/usbc/usb_muxes.h b/zephyr/shim/include/usbc/usb_muxes.h index 21f720517c..9dce1a3aa5 100644 --- a/zephyr/shim/include/usbc/usb_muxes.h +++ b/zephyr/shim/include/usbc/usb_muxes.h @@ -309,6 +309,25 @@ } /** + * @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 * @@ -316,7 +335,7 @@ * @param idx Place in chain */ #define USB_MUX_CHAIN_STRUCT_DECLARE_OP(chain_id, idx) \ - extern USB_MUX_CHAIN_STRUCT_DECLARE(USBC_PORT(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 @@ -358,6 +377,17 @@ [USBC_PORT(chain_id)] = USB_MUX_CHAIN_STRUCT_INIT(chain_id, 0), /** + * @brief Call @p op only if chain @p chain_id is not alternative + * + * @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_FOR_MAIN_CHAIN(chain_id, op, ...) \ + COND_CODE_0(DT_PROP(chain_id, alternative_chain), \ + (op(chain_id, ##__VA_ARGS__)), ()) + +/** * @brief Call @p op for each USB mux chain * * @param op Operation to perform on USB mux chain @@ -423,6 +453,36 @@ (USB_MUX_FOREACH_CHAIN_VARGS(USB_MUX_FIND_PORT, mux_id)(-1)) /** + * @brief Set usb_mux_chain structure for mux @p idx in chain @p chain_id + * + * @param chain_id Alternative USB mux chain node ID + * @param idx Position of the mux in chain + */ +#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 Enable alternative USB mux chain + * + * @param chain_id Alternative USB mux chain node ID + */ +#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>; */ @@ -434,6 +494,6 @@ USB_MUX_FOREACH_MUX(USB_MUX_DECLARE) * 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_OP) + USB_MUX_CHAIN_STRUCT_DECLARE_EXTERN_OP) #endif /* ZEPHYR_CHROME_USBC_USB_MUXES_H */ diff --git a/zephyr/shim/src/usb_muxes.c b/zephyr/shim/src/usb_muxes.c index e85a095db0..d9f14d0c67 100644 --- a/zephyr/shim/src/usb_muxes.c +++ b/zephyr/shim/src/usb_muxes.c @@ -43,7 +43,15 @@ USB_MUX_FOREACH_MUX(USB_MUX_CHECK_ALL_PORTS_ARE_SAME) /** - * Define usb_mux_chain structures e.g. + * Declare all usb_mux_chain structures e.g. + * MAYBE_CONST struct usb_mux_chain + * USB_MUX_chain_port_<port_id>_mux_<position_id>; + */ +USB_MUX_FOREACH_CHAIN_VARGS(USB_MUX_FOREACH_NO_ROOT_MUX, + USB_MUX_CHAIN_STRUCT_DECLARE_OP) + +/** + * Define usb_mux_chain structures for main chain e.g. * * MAYBE_CONST struct usb_mux_chain * USB_MUX_chain_port_<port_id>_mux_<position_id> = { @@ -51,7 +59,7 @@ USB_MUX_FOREACH_MUX(USB_MUX_CHECK_ALL_PORTS_ARE_SAME) * .next = &USB_MUX_chain_port_0_mux_1, * } */ -USB_MUX_FOREACH_CHAIN_VARGS(USB_MUX_FOREACH_NO_ROOT_MUX, +USB_MUX_FOREACH_CHAIN_VARGS(USB_MUX_FOR_MAIN_CHAIN, USB_MUX_FOREACH_NO_ROOT_MUX, USB_MUX_CHAIN_STRUCT_DEFINE_OP) /** @@ -70,8 +78,8 @@ USB_MUX_FOREACH_MUX(USB_MUX_CB_BOARD_SET_DECLARE_IF_EXISTS) * }, * [1] = { ... }, */ -MAYBE_CONST struct usb_mux_chain usb_muxes[] = { USB_MUX_FOREACH_CHAIN( - USB_MUX_DEFINE_ROOT_MUX) }; +MAYBE_CONST struct usb_mux_chain usb_muxes[] = { USB_MUX_FOREACH_CHAIN_VARGS( + USB_MUX_FOR_MAIN_CHAIN, USB_MUX_DEFINE_ROOT_MUX) }; BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == CONFIG_USB_PD_PORT_MAX_COUNT); /** |