diff options
| -rw-r--r-- | Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml | 4 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/net/can/ti,am3517-hecc.yaml | 64 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/net/can/ti_hecc.txt | 32 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/net/can/xilinx,can.yaml | 5 | ||||
| -rw-r--r-- | Documentation/networking/device_drivers/can/ctu/fsm_txt_buffer_user.svg | 4 | ||||
| -rw-r--r-- | MAINTAINERS | 2 | ||||
| -rw-r--r-- | drivers/net/can/m_can/m_can.c | 2 | ||||
| -rw-r--r-- | drivers/net/can/m_can/m_can_pci.c | 6 | ||||
| -rw-r--r-- | drivers/net/can/m_can/tcan4x5x-core.c | 31 | ||||
| -rw-r--r-- | drivers/net/can/rockchip/rockchip_canfd-core.c | 17 | ||||
| -rw-r--r-- | drivers/net/can/rockchip/rockchip_canfd-rx.c | 5 | ||||
| -rw-r--r-- | drivers/net/can/rockchip/rockchip_canfd.h | 14 | ||||
| -rw-r--r-- | drivers/net/can/usb/gs_usb.c | 2 | ||||
| -rw-r--r-- | drivers/net/can/vxcan.c | 26 |
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] = { |
