Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

can: dev: add transceiver capabilities to xilinx_can

Currently the xilinx_can driver does not support adding a phy like the
"ti,tcan1043" to its devicetree.

This code makes it possible to add such phy, so that the kernel makes
sure that the PHY is in operational state, when the link is set to an
"up" state.

Signed-off-by: Marcel Hellwig <git@cookiesoft.de>
Link: https://lore.kernel.org/r/20230417085204.179268-1-git@cookiesoft.de
[mkl: call phy_power_off() after pm_runtime_put()]
[mkl: remove error message for phy_power_on() failure]
[mkl: update kernel-doc for struct xcan_priv]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Marcel Hellwig and committed by
Marc Kleine-Budde
d7588f02 843b8464

+19
+19
drivers/net/can/xilinx_can.c
··· 28 28 #include <linux/types.h> 29 29 #include <linux/can/dev.h> 30 30 #include <linux/can/error.h> 31 + #include <linux/phy/phy.h> 31 32 #include <linux/pm_runtime.h> 32 33 33 34 #define DRIVER_NAME "xilinx_can" ··· 199 198 * @bus_clk: Pointer to struct clk 200 199 * @can_clk: Pointer to struct clk 201 200 * @devtype: Device type specific constants 201 + * @transceiver: Optional pointer to associated CAN transceiver 202 202 */ 203 203 struct xcan_priv { 204 204 struct can_priv can; ··· 217 215 struct clk *bus_clk; 218 216 struct clk *can_clk; 219 217 struct xcan_devtype_data devtype; 218 + struct phy *transceiver; 220 219 }; 221 220 222 221 /* CAN Bittiming constants as per Xilinx CAN specs */ ··· 1422 1419 struct xcan_priv *priv = netdev_priv(ndev); 1423 1420 int ret; 1424 1421 1422 + ret = phy_power_on(priv->transceiver); 1423 + if (ret) 1424 + return ret; 1425 + 1425 1426 ret = pm_runtime_get_sync(priv->dev); 1426 1427 if (ret < 0) { 1427 1428 netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", ··· 1469 1462 free_irq(ndev->irq, ndev); 1470 1463 err: 1471 1464 pm_runtime_put(priv->dev); 1465 + phy_power_off(priv->transceiver); 1472 1466 1473 1467 return ret; 1474 1468 } ··· 1491 1483 close_candev(ndev); 1492 1484 1493 1485 pm_runtime_put(priv->dev); 1486 + phy_power_off(priv->transceiver); 1494 1487 1495 1488 return 0; 1496 1489 } ··· 1722 1713 { 1723 1714 struct net_device *ndev; 1724 1715 struct xcan_priv *priv; 1716 + struct phy *transceiver; 1725 1717 const struct of_device_id *of_id; 1726 1718 const struct xcan_devtype_data *devtype = &xcan_axi_data; 1727 1719 void __iomem *addr; ··· 1853 1843 goto err_free; 1854 1844 } 1855 1845 1846 + transceiver = devm_phy_optional_get(&pdev->dev, NULL); 1847 + if (IS_ERR(transceiver)) { 1848 + ret = PTR_ERR(transceiver); 1849 + dev_err_probe(&pdev->dev, ret, "failed to get phy\n"); 1850 + goto err_free; 1851 + } 1852 + priv->transceiver = transceiver; 1853 + 1856 1854 priv->write_reg = xcan_write_reg_le; 1857 1855 priv->read_reg = xcan_read_reg_le; 1858 1856 ··· 1887 1869 goto err_disableclks; 1888 1870 } 1889 1871 1872 + of_can_transceiver(ndev); 1890 1873 pm_runtime_put(&pdev->dev); 1891 1874 1892 1875 if (priv->devtype.flags & XCAN_FLAG_CANFD_2) {