summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml4
-rw-r--r--Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml64
-rw-r--r--Documentation/devicetree/bindings/net/can/ti_hecc.txt32
-rw-r--r--Documentation/devicetree/bindings/net/can/xilinx,can.yaml5
-rw-r--r--Documentation/networking/device_drivers/can/ctu/fsm_txt_buffer_user.svg4
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/net/can/m_can/m_can.c2
-rw-r--r--drivers/net/can/m_can/m_can_pci.c6
-rw-r--r--drivers/net/can/m_can/tcan4x5x-core.c31
-rw-r--r--drivers/net/can/rockchip/rockchip_canfd-core.c17
-rw-r--r--drivers/net/can/rockchip/rockchip_canfd-rx.c5
-rw-r--r--drivers/net/can/rockchip/rockchip_canfd.h14
-rw-r--r--drivers/net/can/usb/gs_usb.c2
-rw-r--r--drivers/net/can/vxcan.c26
14 files changed, 155 insertions, 59 deletions
diff --git a/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml b/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml
index a077c0330013..81e2b6dfeb02 100644
--- a/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml
+++ b/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml
@@ -16,7 +16,9 @@ allOf:
properties:
compatible:
oneOf:
- - const: rockchip,rk3568v2-canfd
+ - enum:
+ - rockchip,rk3568v2-canfd
+ - rockchip,rk3588-canfd
- items:
- const: rockchip,rk3568v3-canfd
- const: rockchip,rk3568v2-canfd
diff --git a/Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml b/Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml
new file mode 100644
index 000000000000..7874e9e49224
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/can/ti,am3517-hecc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments High End CAN Controller (HECC)
+
+maintainers:
+ - Eduard Bostina <egbostina@gmail.com>
+
+allOf:
+ - $ref: can-controller.yaml#
+
+properties:
+ compatible:
+ const: ti,am3517-hecc
+
+ reg:
+ maxItems: 3
+
+ reg-names:
+ items:
+ - const: hecc
+ - const: hecc-ram
+ - const: mbx
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ ti,use-hecc1int:
+ type: boolean
+ description:
+ If provided, configures HECC to produce all interrupts on the
+ HECC1INT interrupt line. By default, the HECC0INT interrupt line
+ will be used.
+ default: false
+
+ xceiver-supply:
+ description: Regulator that powers the CAN transceiver.
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ can@5c050000 {
+ compatible = "ti,am3517-hecc";
+ reg = <0x5c050000 0x80>,
+ <0x5c053000 0x180>,
+ <0x5c052000 0x200>;
+ reg-names = "hecc", "hecc-ram", "mbx";
+ interrupts = <24>;
+ clocks = <&hecc_ck>;
+ };
diff --git a/Documentation/devicetree/bindings/net/can/ti_hecc.txt b/Documentation/devicetree/bindings/net/can/ti_hecc.txt
deleted file mode 100644
index e0f0a7cfe329..000000000000
--- a/Documentation/devicetree/bindings/net/can/ti_hecc.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Texas Instruments High End CAN Controller (HECC)
-================================================
-
-This file provides information, what the device node
-for the hecc interface contains.
-
-Required properties:
-- compatible: "ti,am3517-hecc"
-- reg: addresses and lengths of the register spaces for 'hecc', 'hecc-ram'
- and 'mbx'
-- reg-names :"hecc", "hecc-ram", "mbx"
-- interrupts: interrupt mapping for the hecc interrupts sources
-- clocks: clock phandles (see clock bindings for details)
-
-Optional properties:
-- ti,use-hecc1int: if provided configures HECC to produce all interrupts
- on HECC1INT interrupt line. By default HECC0INT interrupt
- line will be used.
-- xceiver-supply: regulator that powers the CAN transceiver
-
-Example:
-
-For am3517evm board:
- hecc: can@5c050000 {
- compatible = "ti,am3517-hecc";
- reg = <0x5c050000 0x80>,
- <0x5c053000 0x180>,
- <0x5c052000 0x200>;
- reg-names = "hecc", "hecc-ram", "mbx";
- interrupts = <24>;
- clocks = <&hecc_ck>;
- };
diff --git a/Documentation/devicetree/bindings/net/can/xilinx,can.yaml b/Documentation/devicetree/bindings/net/can/xilinx,can.yaml
index 40835497050a..18015e60fd6d 100644
--- a/Documentation/devicetree/bindings/net/can/xilinx,can.yaml
+++ b/Documentation/devicetree/bindings/net/can/xilinx,can.yaml
@@ -8,7 +8,7 @@ title:
Xilinx CAN and CANFD controller
maintainers:
- - Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+ - Harini T <harini.t@amd.com>
properties:
compatible:
@@ -53,6 +53,9 @@ properties:
$ref: /schemas/types.yaml#/definitions/flag
description: CAN TX_OL, TX_TL and RX FIFOs have ECC support(AXI CAN)
+ phys:
+ maxItems: 1
+
required:
- compatible
- reg
diff --git a/Documentation/networking/device_drivers/can/ctu/fsm_txt_buffer_user.svg b/Documentation/networking/device_drivers/can/ctu/fsm_txt_buffer_user.svg
index 381323423b4c..c8cf0bc49b69 100644
--- a/Documentation/networking/device_drivers/can/ctu/fsm_txt_buffer_user.svg
+++ b/Documentation/networking/device_drivers/can/ctu/fsm_txt_buffer_user.svg
@@ -93,9 +93,9 @@
<ellipse cx="144.827" cy="159.143" rx="10.8866" ry="4.39308"/>
<ellipse cx="59.4364" cy="142.823" rx="7.36455" ry="4.39308"/>
<ellipse cx="144.827" cy="129.196" rx="10.8866" ry="4.39308"/>
- <ellipse cx="143.077" cy="180.53" rx="10.8866" ry="4.39308"/>
</g>
- <ellipse cx="110.386" cy="180.53" rx="10.8866" ry="4.39308" fill="#ffcb35" stroke="#000" stroke-linecap="square" stroke-width=".499999"/>
+ <ellipse cx="110.386" cy="180.53" rx="10.8866" ry="4.39308" fill="#28a4ff" stroke="#000" stroke-linecap="square" stroke-width=".499999"/>
+ <ellipse cx="143.077" cy="180.53" rx="10.8866" ry="4.39308" fill="#ffcb35" stroke="#000" stroke-linecap="square" stroke-width=".499999"/>
<text x="110.90907" y="179.42688" font-size="3.175px" xml:space="preserve"><tspan x="110.90907" y="179.42688" dy="0.60000002" text-align="center" text-anchor="middle">Accessible</tspan><tspan x="110.90907" y="183.39563"><tspan font-size="3.175px" text-align="center" text-anchor="middle">for S</tspan>W</tspan></text>
<text x="143.5869" y="179.52795" xml:space="preserve"><tspan x="143.5869" y="179.52795" dy="1 0 0 0 0 0" font-family="sans-serif" font-size="2.82222px" text-align="center" text-anchor="middle" style="font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal">Inaccessible</tspan><tspan x="143.5869" y="183.36786" font-size="3.175px"><tspan font-size="3.175px" text-align="center" text-anchor="middle">for S</tspan>W</tspan></text>
<g font-size="3.175px">
diff --git a/MAINTAINERS b/MAINTAINERS
index 906000a4414a..6eee2c2aa6ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -29576,7 +29576,7 @@ F: Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml
F: drivers/net/ethernet/xilinx/xilinx_axienet*
XILINX CAN DRIVER
-M: Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+M: Harini T <harini.t@amd.com>
L: linux-can@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/can/xilinx,can.yaml
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index eb856547ae7d..16f80607e150 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -2464,7 +2464,7 @@ struct m_can_classdev *m_can_class_allocate_dev(struct device *dev,
return ERR_PTR(ret);
}
- if (dev->of_node && of_property_read_bool(dev->of_node, "wakeup-source"))
+ if (dev->of_node && of_property_present(dev->of_node, "wakeup-source"))
device_set_wakeup_capable(dev, true);
/* Get TX FIFO size
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
index eb31ed1f9644..d11a7c88fc32 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
@@ -126,7 +126,7 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
mcan_class->net->irq = pci_irq_vector(pci, 0);
mcan_class->pm_clock_support = 1;
mcan_class->pm_wake_source = 0;
- mcan_class->can.clock.freq = id->driver_data;
+ mcan_class->can.clock.freq = M_CAN_CLOCK_FREQ_EHL;
mcan_class->irq_edge_triggered = true;
mcan_class->ops = &m_can_pci_ops;
@@ -183,8 +183,8 @@ static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
m_can_pci_suspend, m_can_pci_resume);
static const struct pci_device_id m_can_pci_id_table[] = {
- { PCI_VDEVICE(INTEL, 0x4bc1), M_CAN_CLOCK_FREQ_EHL, },
- { PCI_VDEVICE(INTEL, 0x4bc2), M_CAN_CLOCK_FREQ_EHL, },
+ { PCI_VDEVICE(INTEL, 0x4bc1) },
+ { PCI_VDEVICE(INTEL, 0x4bc2) },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, m_can_pci_id_table);
diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c
index 31cc9d0abd45..a5b8829aa519 100644
--- a/drivers/net/can/m_can/tcan4x5x-core.c
+++ b/drivers/net/can/m_can/tcan4x5x-core.c
@@ -211,8 +211,31 @@ static int tcan4x5x_write_fifo(struct m_can_classdev *cdev,
return regmap_bulk_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
}
-static int tcan4x5x_power_enable(struct regulator *reg, int enable)
+static int tcan4x5x_power_enable(struct tcan4x5x_priv *priv, int enable)
{
+ struct regulator *reg = priv->power;
+
+ /*
+ * Put the device into sleep mode if the RST pin is available,
+ * since a wake-up event, RST pin toggle, or power cycle are the only
+ * ways to exit sleep mode.
+ * Redundant if the regulator is exclusive to this device, but that
+ * can't be determined here.
+ *
+ * Datasheet: TCAN4550, section "8.4.3 Sleep Mode"
+ * https://www.ti.com/lit/gpn/tcan4550
+ */
+ if (priv->reset_gpio && !enable) {
+ int ret;
+
+ ret = regmap_update_bits(priv->regmap, TCAN4X5X_CONFIG,
+ TCAN4X5X_MODE_SEL_MASK,
+ TCAN4X5X_MODE_SLEEP);
+ if (ret)
+ dev_err(&priv->spi->dev, "Setting sleep mode failed %pe\n",
+ ERR_PTR(ret));
+ }
+
if (IS_ERR_OR_NULL(reg))
return 0;
@@ -476,7 +499,7 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
goto out_m_can_class_free_dev;
}
- ret = tcan4x5x_power_enable(priv->power, 1);
+ ret = tcan4x5x_power_enable(priv, 1);
if (ret) {
dev_err(&spi->dev, "Enabling regulator failed %pe\n",
ERR_PTR(ret));
@@ -531,7 +554,7 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
return 0;
out_power:
- tcan4x5x_power_enable(priv->power, 0);
+ tcan4x5x_power_enable(priv, 0);
out_m_can_class_free_dev:
m_can_class_free_dev(mcan_class->net);
return ret;
@@ -543,7 +566,7 @@ static void tcan4x5x_can_remove(struct spi_device *spi)
m_can_class_unregister(&priv->cdev);
- tcan4x5x_power_enable(priv->power, 0);
+ tcan4x5x_power_enable(priv, 0);
m_can_class_free_dev(priv->cdev.net);
}
diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index 29de0c01e4ed..37c1c22c40c9 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -50,6 +50,12 @@ static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v3 = {
RKCANFD_QUIRK_CANFD_BROKEN,
};
+static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3588 = {
+ .model = RKCANFD_MODEL_RK3588,
+ .quirks = RKCANFD_QUIRK_RK3568_ERRATUM_5 |
+ RKCANFD_QUIRK_RK3568_ERRATUM_6,
+};
+
static const char *__rkcanfd_get_model_str(enum rkcanfd_model model)
{
switch (model) {
@@ -57,6 +63,8 @@ static const char *__rkcanfd_get_model_str(enum rkcanfd_model model)
return "rk3568v2";
case RKCANFD_MODEL_RK3568V3:
return "rk3568v3";
+ case RKCANFD_MODEL_RK3588:
+ return "rk3588";
}
return "<unknown>";
@@ -148,6 +156,12 @@ static int rkcanfd_set_bittiming(struct rkcanfd_priv *priv)
rkcanfd_write(priv, RKCANFD_REG_FD_DATA_BITTIMING, reg_dbt);
+ /* RK3588 CAN-FD BRS works with TDC disabled. */
+ if (priv->devtype_data.model == RKCANFD_MODEL_RK3588) {
+ rkcanfd_write(priv, RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION, 0);
+ return 0;
+ }
+
tdco = (priv->can.clock.freq / dbt->bitrate) * 2 / 3;
tdco = min(tdco, FIELD_MAX(RKCANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_OFFSET));
@@ -847,6 +861,9 @@ static const struct of_device_id rkcanfd_of_match[] = {
.compatible = "rockchip,rk3568v3-canfd",
.data = &rkcanfd_devtype_data_rk3568v3,
}, {
+ .compatible = "rockchip,rk3588-canfd",
+ .data = &rkcanfd_devtype_data_rk3588,
+ }, {
/* sentinel */
},
};
diff --git a/drivers/net/can/rockchip/rockchip_canfd-rx.c b/drivers/net/can/rockchip/rockchip_canfd-rx.c
index 475c0409e215..24e87daa1df0 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-rx.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-rx.c
@@ -281,7 +281,10 @@ rkcanfd_rx_fifo_get_len(const struct rkcanfd_priv *priv)
{
const u32 reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
- return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT, reg);
+ if (priv->devtype_data.model == RKCANFD_MODEL_RK3588)
+ return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT_RK3588, reg);
+
+ return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT_RK3568, reg);
}
int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv)
diff --git a/drivers/net/can/rockchip/rockchip_canfd.h b/drivers/net/can/rockchip/rockchip_canfd.h
index 93131c7d7f54..95bea9bfd8a2 100644
--- a/drivers/net/can/rockchip/rockchip_canfd.h
+++ b/drivers/net/can/rockchip/rockchip_canfd.h
@@ -214,7 +214,8 @@
#define RKCANFD_REG_TXEVENT_FIFO_CTRL_TXE_FIFO_ENABLE BIT(0)
#define RKCANFD_REG_RX_FIFO_CTRL 0x118
-#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT GENMASK(6, 4)
+#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT_RK3568 GENMASK(6, 4)
+#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT_RK3588 GENMASK(7, 5)
#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_FULL_WATERMARK GENMASK(3, 1)
#define RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE BIT(0)
@@ -331,6 +332,11 @@
* rarely with the standard clock of 300 MHz, but almost immediately
* at 80 MHz.
*
+ * Tests on the rk3588 show the same empty FIFO condition.
+ * In that setup rx_fifo_empty_errors increments when the bus
+ * transitions from idle to high CAN-FD load and stops growing once
+ * the bus reaches a steady state.
+ *
* To workaround this problem, check for empty FIFO with
* rkcanfd_fifo_header_empty() in rkcanfd_handle_rx_int_one() and exit
* early.
@@ -344,6 +350,8 @@
/* Erratum 6: The CAN controller's transmission of extended frames may
* intermittently change into standard frames
*
+ * Tests on the rk3588 show the same problem.
+ *
* Work around this issue by activating self reception (RXSTX). If we
* have pending TX CAN frames, check all RX'ed CAN frames in
* rkcanfd_rxstx_filter().
@@ -424,6 +432,9 @@
* cansequence -rv -i 1
*
* - TX starvation after repeated Bus-Off
+ * Tests on the rk3588 show the same problem. In a
+ * 10-cycle Bus-Off recovery test, 9 cycles failed to send after the
+ * controller restarted.
* To reproduce:
* host:
* sleep 3 && cangen can0 -I2 -Li -Di -p10 -g 0.0
@@ -434,6 +445,7 @@
enum rkcanfd_model {
RKCANFD_MODEL_RK3568V2 = 0x35682,
RKCANFD_MODEL_RK3568V3 = 0x35683,
+ RKCANFD_MODEL_RK3588 = 0x3588,
};
struct rkcanfd_devtype_data {
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 82508a865095..3b9b2f104d86 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -1565,7 +1565,7 @@ static int gs_usb_probe(struct usb_interface *intf,
if (icount > type_max(parent->channel_cnt)) {
dev_err(&intf->dev,
- "Driver cannot handle more that %u CAN interfaces\n",
+ "Driver cannot handle more than %u CAN interfaces\n",
type_max(parent->channel_cnt));
return -EINVAL;
}
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index e882250180ef..9e2e25d02471 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -33,6 +33,7 @@ MODULE_ALIAS_RTNL_LINK(DRV_NAME);
struct vxcan_priv {
struct net_device __rcu *peer;
+ netdevice_tracker peer_tracker;
};
static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev)
@@ -268,9 +269,11 @@ static int vxcan_newlink(struct net_device *dev,
/* cross link the device pair */
priv = netdev_priv(dev);
rcu_assign_pointer(priv->peer, peer);
+ netdev_hold(peer, &priv->peer_tracker, GFP_KERNEL);
priv = netdev_priv(peer);
rcu_assign_pointer(priv->peer, dev);
+ netdev_hold(dev, &priv->peer_tracker, GFP_KERNEL);
return 0;
@@ -281,24 +284,25 @@ unregister_network_device:
static void vxcan_dellink(struct net_device *dev, struct list_head *head)
{
+ netdevice_tracker *peer_tracker;
struct vxcan_priv *priv;
struct net_device *peer;
priv = netdev_priv(dev);
- peer = rtnl_dereference(priv->peer);
+ peer_tracker = &priv->peer_tracker;
+ peer = unrcu_pointer(xchg(&priv->peer, NULL));
+ if (!peer)
+ return;
- /* Note : dellink() is called from default_device_exit_batch(),
- * before a rcu_synchronize() point. The devices are guaranteed
- * not being freed before one RCU grace period.
- */
- RCU_INIT_POINTER(priv->peer, NULL);
unregister_netdevice_queue(dev, head);
- if (peer) {
- priv = netdev_priv(peer);
- RCU_INIT_POINTER(priv->peer, NULL);
- unregister_netdevice_queue(peer, head);
- }
+ priv = netdev_priv(peer);
+ dev = unrcu_pointer(xchg(&priv->peer, NULL));
+ if (dev)
+ unregister_netdevice_queue_net(dev_net(dev), peer, head);
+
+ netdev_put(peer, peer_tracker);
+ netdev_put(dev, &priv->peer_tracker);
}
static const struct nla_policy vxcan_policy[VXCAN_INFO_MAX + 1] = {