Skip to content

Commit

Permalink
Merge patch series "can: xilinx_can: Add support for reset"
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Marc Kleine-Budde committed Jul 19, 2023
2 parents 22d8e8d + 25000fc commit 2e12d79
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
3 changes: 3 additions & 0 deletions Documentation/devicetree/bindings/net/can/xilinx,can.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 21 additions & 4 deletions drivers/net/can/xilinx_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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:
Expand All @@ -1920,9 +1935,11 @@ static int xcan_probe(struct platform_device *pdev)
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);
}

Expand Down

0 comments on commit 2e12d79

Please sign in to comment.