5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Faiz Abbas faiz_abbas@ti.com
[ 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@pengutronix.de Signed-off-by: Faiz Abbas faiz_abbas@ti.com Signed-off-by: Aswath Govindraju a-govindraju@ti.com Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Stable-dep-of: 2c09b50efcad ("can: m_can: m_can_close(): stop clocks after device has been shut down") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/net/can/m_can/m_can.c | 11 ++++++++++- drivers/net/can/m_can/m_can.h | 2 ++ drivers/net/can/m_can/m_can_platform.c | 13 +++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-)
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;