diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2023-07-19 09:57:05 +0300 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2023-07-19 09:57:05 +0300 |
commit | 2e12d79f56ffe76371b594e83f50772fe36feea4 (patch) | |
tree | 31733a2a2b2a883b1e9792707e5d96907156bdef | |
parent | 22d8e8d6338d17bc192559dad24d1e45be0f9795 (diff) | |
parent | 25000fc785b4cf034466ff547eabf2adcf1845bc (diff) | |
download | linux-2e12d79f56ffe76371b594e83f50772fe36feea4.tar.xz |
Merge patch series "can: xilinx_can: Add support for reset"
Michal Simek <michal.simek@amd.com> says:
IP core has option reset line which can be wired that's why add
support for optional reset.
Changes in v2:
- Add Conor's ACK
- Fix use-after-free in xcan_remove reported by Marc.
- Link to v1: https://lore.kernel.org/all/cover.1689084227.git.michal.simek@amd.com
Link: https://lore.kernel.org/all/cover.1689164442.git.michal.simek@amd.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r-- | Documentation/devicetree/bindings/net/can/xilinx,can.yaml | 3 | ||||
-rw-r--r-- | drivers/net/can/xilinx_can.c | 25 |
2 files changed, 24 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/net/can/xilinx,can.yaml b/Documentation/devicetree/bindings/net/can/xilinx,can.yaml index 897d2cbda45b..64d57c343e6f 100644 --- a/Documentation/devicetree/bindings/net/can/xilinx,can.yaml +++ b/Documentation/devicetree/bindings/net/can/xilinx,can.yaml @@ -46,6 +46,9 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 description: CAN Tx mailbox buffer count (CAN FD) + resets: + maxItems: 1 + required: - compatible - reg diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 4d3283db3a13..abe58f103043 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -30,6 +30,7 @@ #include <linux/can/error.h> #include <linux/phy/phy.h> #include <linux/pm_runtime.h> +#include <linux/reset.h> #define DRIVER_NAME "xilinx_can" @@ -200,6 +201,7 @@ struct xcan_devtype_data { * @can_clk: Pointer to struct clk * @devtype: Device type specific constants * @transceiver: Optional pointer to associated CAN transceiver + * @rstc: Pointer to reset control */ struct xcan_priv { struct can_priv can; @@ -218,6 +220,7 @@ struct xcan_priv { struct clk *can_clk; struct xcan_devtype_data devtype; struct phy *transceiver; + struct reset_control *rstc; }; /* CAN Bittiming constants as per Xilinx CAN specs */ @@ -1799,6 +1802,16 @@ static int xcan_probe(struct platform_device *pdev) priv->can.do_get_berr_counter = xcan_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_BERR_REPORTING; + priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + if (IS_ERR(priv->rstc)) { + dev_err(&pdev->dev, "Cannot get CAN reset.\n"); + ret = PTR_ERR(priv->rstc); + goto err_free; + } + + ret = reset_control_reset(priv->rstc); + if (ret) + goto err_free; if (devtype->cantype == XAXI_CANFD) { priv->can.data_bittiming_const = @@ -1827,7 +1840,7 @@ static int xcan_probe(struct platform_device *pdev) /* Get IRQ for the device */ ret = platform_get_irq(pdev, 0); if (ret < 0) - goto err_free; + goto err_reset; ndev->irq = ret; @@ -1843,21 +1856,21 @@ static int xcan_probe(struct platform_device *pdev) if (IS_ERR(priv->can_clk)) { ret = dev_err_probe(&pdev->dev, PTR_ERR(priv->can_clk), "device clock not found\n"); - goto err_free; + goto err_reset; } priv->bus_clk = devm_clk_get(&pdev->dev, devtype->bus_clk_name); if (IS_ERR(priv->bus_clk)) { ret = dev_err_probe(&pdev->dev, PTR_ERR(priv->bus_clk), "bus clock not found\n"); - goto err_free; + goto err_reset; } 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 err_free; + goto err_reset; } priv->transceiver = transceiver; @@ -1904,6 +1917,8 @@ static int xcan_probe(struct platform_device *pdev) err_disableclks: pm_runtime_put(priv->dev); pm_runtime_disable(&pdev->dev); +err_reset: + reset_control_assert(priv->rstc); err_free: free_candev(ndev); err: @@ -1920,9 +1935,11 @@ err: static void xcan_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct xcan_priv *priv = netdev_priv(ndev); unregister_candev(ndev); pm_runtime_disable(&pdev->dev); + reset_control_assert(priv->rstc); free_candev(ndev); } |