Commit d80bfde3 authored by Dimitri Fedrau's avatar Dimitri Fedrau Committed by Marc Kleine-Budde
Browse files

can: flexcan: add transceiver capabilities



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: default avatarDimitri Fedrau <dimitri.fedrau@liebherr.com>
Link: https://patch.msgid.link/20250312-flexcan-add-transceiver-caps-v4-2-29e89ae0225a@liebherr.com


Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 6263bad8
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -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>
@@ -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 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 0;
}

static int flexcan_chip_enable(struct flexcan_priv *priv)
@@ -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;
@@ -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);
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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;