mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-28 17:13:13 -05:00
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>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user