summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2025-03-18 12:39:57 +0100
committerPaolo Abeni <pabeni@redhat.com>2025-03-18 12:39:58 +0100
commit15f9e34a499e896075d562ee47aac36e0e380d6a (patch)
tree227ab010dc57e66bd6e0806dd88931a3dbee6fdc
parented6bcbe39ee446203a356eadf4fa1256a5026457 (diff)
parent6bffe88452dbe284747442f10a7ac8249d6495d7 (diff)
Merge tag 'linux-can-next-for-6.15-20250314' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
Marc Kleine-Budde says: ==================== pull-request: can-next 2025-03-14 this is a pull request of 4 patches for net-next/main. In the first 2 patches by Dimitri Fedrau add CAN transceiver support to the flexcan driver. Frank Li's patch adds i.MX94 support to the flexcan device tree bindings. The last patch is by Davide Caratti and adds protocol counter for AF_CAN sockets. linux-can-next-for-6.15-20250314 * tag 'linux-can-next-for-6.15-20250314' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next: can: add protocol counter for AF_CAN sockets dt-bindings: can: fsl,flexcan: add i.MX94 support can: flexcan: add transceiver capabilities dt-bindings: can: fsl,flexcan: add transceiver capabilities ==================== Link: https://patch.msgid.link/20250314132327.2905693-1-mkl@pengutronix.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml13
-rw-r--r--drivers/net/can/flexcan/flexcan-core.c27
-rw-r--r--drivers/net/can/flexcan/flexcan.h1
-rw-r--r--net/can/af_can.c2
-rw-r--r--net/can/bcm.c1
-rw-r--r--net/can/isotp.c1
-rw-r--r--net/can/raw.c5
7 files changed, 43 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml b/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
index 73252fe56fe6..f81d56f7c12a 100644
--- a/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
+++ b/Documentation/devicetree/bindings/net/can/fsl,flexcan.yaml
@@ -45,6 +45,10 @@ properties:
- enum:
- nxp,s32g3-flexcan
- const: nxp,s32g2-flexcan
+ - items:
+ - enum:
+ - fsl,imx94-flexcan
+ - const: fsl,imx95-flexcan
reg:
maxItems: 1
@@ -77,6 +81,9 @@ properties:
xceiver-supply:
description: Regulator that powers the CAN transceiver.
+ phys:
+ maxItems: 1
+
big-endian:
$ref: /schemas/types.yaml#/definitions/flag
description: |
@@ -171,6 +178,12 @@ allOf:
interrupts:
maxItems: 1
interrupt-names: false
+ - if:
+ required:
+ - xceiver-supply
+ then:
+ properties:
+ phys: false
additionalProperties: false
diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c
index b347a1c93536..7588cb54a909 100644
--- a/drivers/net/can/flexcan/flexcan-core.c
+++ b/drivers/net/can/flexcan/flexcan-core.c
@@ -26,6 +26,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/can/platform/flexcan.h>
+#include <linux/phy/phy.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
@@ -644,18 +645,22 @@ static void flexcan_clks_disable(const struct flexcan_priv *priv)
static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
{
- if (!priv->reg_xceiver)
- return 0;
+ if (priv->reg_xceiver)
+ return regulator_enable(priv->reg_xceiver);
+ else if (priv->transceiver)
+ return phy_power_on(priv->transceiver);
- return regulator_enable(priv->reg_xceiver);
+ return 0;
}
static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
{
- if (!priv->reg_xceiver)
- return 0;
+ if (priv->reg_xceiver)
+ return regulator_disable(priv->reg_xceiver);
+ else if (priv->transceiver)
+ return phy_power_off(priv->transceiver);
- return regulator_disable(priv->reg_xceiver);
+ return 0;
}
static int flexcan_chip_enable(struct flexcan_priv *priv)
@@ -2086,6 +2091,7 @@ static int flexcan_probe(struct platform_device *pdev)
struct net_device *dev;
struct flexcan_priv *priv;
struct regulator *reg_xceiver;
+ struct phy *transceiver;
struct clk *clk_ipg = NULL, *clk_per = NULL;
struct flexcan_regs __iomem *regs;
struct flexcan_platform_data *pdata;
@@ -2101,6 +2107,11 @@ static int flexcan_probe(struct platform_device *pdev)
else if (IS_ERR(reg_xceiver))
return PTR_ERR(reg_xceiver);
+ transceiver = devm_phy_optional_get(&pdev->dev, NULL);
+ if (IS_ERR(transceiver))
+ return dev_err_probe(&pdev->dev, PTR_ERR(transceiver),
+ "failed to get phy\n");
+
if (pdev->dev.of_node) {
of_property_read_u32(pdev->dev.of_node,
"clock-frequency", &clock_freq);
@@ -2198,6 +2209,10 @@ static int flexcan_probe(struct platform_device *pdev)
priv->clk_per = clk_per;
priv->clk_src = clk_src;
priv->reg_xceiver = reg_xceiver;
+ priv->transceiver = transceiver;
+
+ if (transceiver)
+ priv->can.bitrate_max = transceiver->attrs.max_link_rate;
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
priv->irq_boff = platform_get_irq(pdev, 1);
diff --git a/drivers/net/can/flexcan/flexcan.h b/drivers/net/can/flexcan/flexcan.h
index 2cf886618c96..16692a2502eb 100644
--- a/drivers/net/can/flexcan/flexcan.h
+++ b/drivers/net/can/flexcan/flexcan.h
@@ -107,6 +107,7 @@ struct flexcan_priv {
struct clk *clk_per;
struct flexcan_devtype_data devtype_data;
struct regulator *reg_xceiver;
+ struct phy *transceiver;
struct flexcan_stop_mode stm;
int irq_boff;
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 01f3fbb3b67d..7b191dbe3693 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -172,6 +172,8 @@ static int can_create(struct net *net, struct socket *sock, int protocol,
sock_orphan(sk);
sock_put(sk);
sock->sk = NULL;
+ } else {
+ sock_prot_inuse_add(net, sk->sk_prot, 1);
}
errout:
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 217049fa496e..6dc041e054ba 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1625,6 +1625,7 @@ static int bcm_release(struct socket *sock)
sock->sk = NULL;
release_sock(sk);
+ sock_prot_inuse_add(net, sk->sk_prot, -1);
sock_put(sk);
return 0;
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 16046931542a..789583c62f98 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -1239,6 +1239,7 @@ static int isotp_release(struct socket *sock)
sock->sk = NULL;
release_sock(sk);
+ sock_prot_inuse_add(net, sk->sk_prot, -1);
sock_put(sk);
return 0;
diff --git a/net/can/raw.c b/net/can/raw.c
index 9b1d5f036f57..020f21430b1d 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -397,11 +397,13 @@ static int raw_release(struct socket *sock)
{
struct sock *sk = sock->sk;
struct raw_sock *ro;
+ struct net *net;
if (!sk)
return 0;
ro = raw_sk(sk);
+ net = sock_net(sk);
spin_lock(&raw_notifier_lock);
while (raw_busy_notifier == ro) {
@@ -421,7 +423,7 @@ static int raw_release(struct socket *sock)
raw_disable_allfilters(dev_net(ro->dev), ro->dev, sk);
netdev_put(ro->dev, &ro->dev_tracker);
} else {
- raw_disable_allfilters(sock_net(sk), NULL, sk);
+ raw_disable_allfilters(net, NULL, sk);
}
}
@@ -440,6 +442,7 @@ static int raw_release(struct socket *sock)
release_sock(sk);
rtnl_unlock();
+ sock_prot_inuse_add(net, sk->sk_prot, -1);
sock_put(sk);
return 0;