Hi Marc, On 22/11/21 6:42 pm, Marc Kleine-Budde wrote: > On 22.11.2021 18:26:24, Aswath Govindraju wrote: >> On some boards, for routing CAN signals from controller to transceiver, >> muxes might need to be set. Therefore, add support for setting the mux by >> reading the mux-controls property from the device tree node. >> >> Signed-off-by: Aswath Govindraju <a-govindraju@xxxxxx> >> --- >> drivers/phy/phy-can-transceiver.c | 26 ++++++++++++++++++++++++++ >> 1 file changed, 26 insertions(+) >> >> diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c >> index 6f3fe37dee0e..15056b9d68ba 100644 >> --- a/drivers/phy/phy-can-transceiver.c >> +++ b/drivers/phy/phy-can-transceiver.c >> @@ -10,6 +10,7 @@ >> #include<linux/module.h> >> #include<linux/gpio.h> >> #include<linux/gpio/consumer.h> >> +#include <linux/mux/consumer.h> >> >> struct can_transceiver_data { >> u32 flags; >> @@ -21,13 +22,23 @@ struct can_transceiver_phy { >> struct phy *generic_phy; >> struct gpio_desc *standby_gpio; >> struct gpio_desc *enable_gpio; >> + struct mux_control *mux_ctrl; >> }; >> >> /* Power on function */ >> static int can_transceiver_phy_power_on(struct phy *phy) >> { >> + int ret; >> struct can_transceiver_phy *can_transceiver_phy = phy_get_drvdata(phy); >> >> + if (can_transceiver_phy->mux_ctrl) { >> + ret = mux_control_select(can_transceiver_phy->mux_ctrl, >> + mux_control_enable_state(can_transceiver_phy->mux_ctrl)); >> + if (ret) { >> + dev_err(&phy->dev, "Failed to select CAN mux: %d\n", ret); >> + return ret; >> + } >> + } >> if (can_transceiver_phy->standby_gpio) >> gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 0); >> if (can_transceiver_phy->enable_gpio) >> @@ -45,6 +56,8 @@ static int can_transceiver_phy_power_off(struct phy *phy) >> gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio, 1); >> if (can_transceiver_phy->enable_gpio) >> gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio, 0); >> + if (can_transceiver_phy->mux_ctrl) >> + mux_control_deselect(can_transceiver_phy->mux_ctrl); >> >> return 0; >> } >> @@ -95,6 +108,19 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) >> match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); >> drvdata = match->data; >> >> + if (of_property_read_bool(dev->of_node, "mux-controls")) { >> + struct mux_control *control; >> + int ret; >> + >> + control = devm_mux_control_get(dev, NULL); >> + if (IS_ERR(control)) { >> + ret = PTR_ERR(control); >> + dev_err_probe(&pdev->dev, ret, "failed to get mux\n"); >> + return PTR_ERR(control); >> + } >> + can_transceiver_phy->mux_ctrl = control; >> + } > > What about adding a devm_mux_control_get_optional(), which doesn't > return a -ENODEV but a NULL pointer if the device doesn't exist? > I tried adding it in the following manner, +/** + * devm_mux_control_optional_get() - Optionally get the mux-control for a + * device, with resource management. + * @dev: The device that needs a mux-control. + * @mux_name: The name identifying the mux-control. + * + * This differs from devm_mux_control_get in that if the mux does not + * exist, it is not considered an error and -ENODEV will not be + * returned. Instead the NULL is returned. + * + * Return: Pointer to the mux-control, or an ERR_PTR with a negative errno. + */ +struct mux_control *devm_mux_control_optional_get(struct device *dev, + const char *mux_name) +{ + struct mux_control *mux_ctrl; + + mux_ctrl = devm_mux_control_get(dev, mux_name); + if (PTR_ERR(mux_ctrl) == -ENOENT) + mux_ctrl = NULL; + + return mux_ctrl; +} +EXPORT_SYMBOL_GPL(devm_mux_control_optional_get); + However the issue is that there is a print in mux_control_get() dev_err(dev, "%pOF: failed to get mux-control %s(%i)\n", which is getting printed, whenever mux-controls property is not found. Therefore, I was not sure about how to go about this issue and did not implement it. Thanks, Aswath > Marc >