Skip to content

Commit

Permalink
can: flexcan: add transceiver capabilities
Browse files Browse the repository at this point in the history
Currently the flexcan driver does only support adding PHYs by using the
"old" regulator bindings. Add support for CAN transceivers as a PHY. Add
the capability to ensure that the PHY is in operational state when the link
is set to an "up" state.

Signed-off-by: Dimitri Fedrau <dimitri.fedrau@liebherr.com>
Link: https://patch.msgid.link/20250312-flexcan-add-transceiver-caps-v4-2-29e89ae0225a@liebherr.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
  • Loading branch information
Dimitri Fedrau authored and Marc Kleine-Budde committed Mar 14, 2025
1 parent 6263bad commit d80bfde
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
27 changes: 21 additions & 6 deletions drivers/net/can/flexcan/flexcan-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/can/platform/flexcan.h>
#include <linux/phy/phy.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
Expand Down Expand Up @@ -644,18 +645,22 @@ static void flexcan_clks_disable(const struct flexcan_priv *priv)

static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
{
if (!priv->reg_xceiver)
return 0;
if (priv->reg_xceiver)
return regulator_enable(priv->reg_xceiver);
else if (priv->transceiver)
return phy_power_on(priv->transceiver);

return regulator_enable(priv->reg_xceiver);
return 0;
}

static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
{
if (!priv->reg_xceiver)
return 0;
if (priv->reg_xceiver)
return regulator_disable(priv->reg_xceiver);
else if (priv->transceiver)
return phy_power_off(priv->transceiver);

return regulator_disable(priv->reg_xceiver);
return 0;
}

static int flexcan_chip_enable(struct flexcan_priv *priv)
Expand Down Expand Up @@ -2086,6 +2091,7 @@ static int flexcan_probe(struct platform_device *pdev)
struct net_device *dev;
struct flexcan_priv *priv;
struct regulator *reg_xceiver;
struct phy *transceiver;
struct clk *clk_ipg = NULL, *clk_per = NULL;
struct flexcan_regs __iomem *regs;
struct flexcan_platform_data *pdata;
Expand All @@ -2101,6 +2107,11 @@ static int flexcan_probe(struct platform_device *pdev)
else if (IS_ERR(reg_xceiver))
return PTR_ERR(reg_xceiver);

transceiver = devm_phy_optional_get(&pdev->dev, NULL);
if (IS_ERR(transceiver))
return dev_err_probe(&pdev->dev, PTR_ERR(transceiver),
"failed to get phy\n");

if (pdev->dev.of_node) {
of_property_read_u32(pdev->dev.of_node,
"clock-frequency", &clock_freq);
Expand Down Expand Up @@ -2198,6 +2209,10 @@ static int flexcan_probe(struct platform_device *pdev)
priv->clk_per = clk_per;
priv->clk_src = clk_src;
priv->reg_xceiver = reg_xceiver;
priv->transceiver = transceiver;

if (transceiver)
priv->can.bitrate_max = transceiver->attrs.max_link_rate;

if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
priv->irq_boff = platform_get_irq(pdev, 1);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/can/flexcan/flexcan.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct flexcan_priv {
struct clk *clk_per;
struct flexcan_devtype_data devtype_data;
struct regulator *reg_xceiver;
struct phy *transceiver;
struct flexcan_stop_mode stm;

int irq_boff;
Expand Down

0 comments on commit d80bfde

Please sign in to comment.