This is a note to let you know that I've just added the patch titled can: m_can: Add support for transceiver as phy to the 5.10-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: can-m_can-add-support-for-transceiver-as-phy.patch and it can be found in the queue-5.10 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 05824e1b551333823db9a8c52d052f623c9d2423 Author: Faiz Abbas <faiz_abbas@xxxxxx> Date: Mon May 10 10:55:41 2021 +0530 can: m_can: Add support for transceiver as phy [ Upstream commit d836cb5fe045463cdab15ad6f278f7c7c194228f ] Add support for implementing transceiver node as phy. The max_bitrate is obtained by getting a phy attribute. Link: https://lore.kernel.org/r/20210724174001.553047-1-mkl@xxxxxxxxxxxxxx Signed-off-by: Faiz Abbas <faiz_abbas@xxxxxx> Signed-off-by: Aswath Govindraju <a-govindraju@xxxxxx> Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> Stable-dep-of: 2c09b50efcad ("can: m_can: m_can_close(): stop clocks after device has been shut down") Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 19a19a7b7deb8..f314d93aca0d9 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -21,6 +21,7 @@ #include <linux/iopoll.h> #include <linux/can/dev.h> #include <linux/pinctrl/consumer.h> +#include <linux/phy/phy.h> #include "m_can.h" @@ -1438,6 +1439,8 @@ static int m_can_close(struct net_device *dev) close_candev(dev); can_led_event(dev, CAN_LED_EVENT_STOP); + phy_power_off(cdev->transceiver); + return 0; } @@ -1624,10 +1627,14 @@ static int m_can_open(struct net_device *dev) struct m_can_classdev *cdev = netdev_priv(dev); int err; - err = m_can_clk_start(cdev); + err = phy_power_on(cdev->transceiver); if (err) return err; + err = m_can_clk_start(cdev); + if (err) + goto out_phy_power_off; + /* open the can device */ err = open_candev(dev); if (err) { @@ -1679,6 +1686,8 @@ static int m_can_open(struct net_device *dev) close_candev(dev); exit_disable_clks: m_can_clk_stop(cdev); +out_phy_power_off: + phy_power_off(cdev->transceiver); return err; } diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index b2699a7c99973..8cad1235afa0b 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -27,6 +27,7 @@ #include <linux/iopoll.h> #include <linux/can/dev.h> #include <linux/pinctrl/consumer.h> +#include <linux/phy/phy.h> /* m_can lec values */ enum m_can_lec_type { @@ -80,6 +81,7 @@ struct m_can_classdev { struct workqueue_struct *tx_wq; struct work_struct tx_work; struct sk_buff *tx_skb; + struct phy *transceiver; struct can_bittiming_const *bit_timing; struct can_bittiming_const *data_timing; diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c index 161cb9be018c0..dbebb9bba545f 100644 --- a/drivers/net/can/m_can/m_can_platform.c +++ b/drivers/net/can/m_can/m_can_platform.c @@ -6,6 +6,7 @@ // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ #include <linux/platform_device.h> +#include <linux/phy/phy.h> #include "m_can.h" @@ -60,6 +61,7 @@ static int m_can_plat_probe(struct platform_device *pdev) struct resource *res; void __iomem *addr; void __iomem *mram_addr; + struct phy *transceiver; int irq, ret = 0; mcan_class = m_can_class_allocate_dev(&pdev->dev); @@ -99,6 +101,16 @@ static int m_can_plat_probe(struct platform_device *pdev) goto probe_fail; } + transceiver = devm_phy_optional_get(&pdev->dev, NULL); + if (IS_ERR(transceiver)) { + ret = PTR_ERR(transceiver); + dev_err_probe(&pdev->dev, ret, "failed to get phy\n"); + goto probe_fail; + } + + if (transceiver) + mcan_class->can.bitrate_max = transceiver->attrs.max_link_rate; + priv->base = addr; priv->mram_base = mram_addr; @@ -106,6 +118,7 @@ static int m_can_plat_probe(struct platform_device *pdev) mcan_class->pm_clock_support = 1; mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk); mcan_class->dev = &pdev->dev; + mcan_class->transceiver = transceiver; mcan_class->ops = &m_can_plat_ops;