mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
linux-can-next-for-6.11-20240621
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEUEC6huC2BN0pvD5fKDiiPnotvG8FAmZ1MB4THG1rbEBwZW5n dXRyb25peC5kZQAKCRAoOKI+ei28b+QQB/9wDkLdjgRsvI3c32IXxTrOmuX97Pm2 jYaHXmH1QkOKK0CXkPLEGjzpxSVXO6/d+ooeINkKmeF9VrtxxYWuE9pEsulyPz4y dbeK5oAZdhtS6CEnArzbNHR6mdP1IcmJ3uKojsV71t+4GTdZw4WHe6LNgC4ua7n8 oYOpgbEV/YP/AyP8vO1L65M+tI69/0jeDpidtDQkNgWepE/Kh0W0ASfqjYrBgvZq eycUmLTCigKNhG8fNJVHejyrnLynY2QBqwM7M5yYw1q8lX4W8Yf1y55VCqzPz63D RiYVdVdG720jk9Ux9ZqxAKBPyzACnV6CG/MnzIgIdpV3O1aEf1WDkU2Y =rRB9 -----END PGP SIGNATURE----- Merge tag 'linux-can-next-for-6.11-20240621' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next Marc Kleine-Budde says: ==================== pull-request: can-next 2024-06-21 The first 2 patches are by Andy Shevchenko, one cleans up the includes in the mcp251x driver, the other one updates the sja100 plx_pci driver to make use of predefines PCI subvendor ID. Mans Rullgard's patch cleans up the Kconfig help text of for the slcan driver. Oliver Hartkopp provides a patch to update the documentation, which removes the ISO 15675-2 specification version where possible. The next 2 patches are by Harini T and update the documentation of the xilinx_can driver. Francesco Valla provides documentation for the ISO 15765-2 protocol. A patch by Dr. David Alan Gilbert removes an unused struct from the mscan driver. 12 patches are by Martin Jocic. The first three add support for 3 new devices to the kvaser_usb driver. The remaining 9 first clean up the kvaser_pciefd driver, and then add support for MSI. Krzysztof Kozlowski contributes 3 patches simplifies the CAN SPI drivers by making use of spi_get_device_match_data(). The last patch is by Martin Hundebøll, which reworks the m_can driver to not enable the CAN transceiver during probe. * tag 'linux-can-next-for-6.11-20240621' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next: (24 commits) can: m_can: don't enable transceiver when probing can: mcp251xfd: simplify with spi_get_device_match_data() can: mcp251x: simplify with spi_get_device_match_data() can: hi311x: simplify with spi_get_device_match_data() can: kvaser_pciefd: Add MSI interrupts can: kvaser_pciefd: Move reset of DMA RX buffers to the end of the ISR can: kvaser_pciefd: Change name of return code variable can: kvaser_pciefd: Rename board_irq to pci_irq can: kvaser_pciefd: Add unlikely can: kvaser_pciefd: Add inline can: kvaser_pciefd: Remove unnecessary comment can: kvaser_pciefd: Skip redundant NULL pointer check in ISR can: kvaser_pciefd: Group #defines together can: kvaser_usb: Add support for Kvaser Mini PCIe 1xCAN can: kvaser_usb: Add support for Kvaser USBcan Pro 5xCAN can: kvaser_usb: Add support for Vining 800 can: mscan: remove unused struct 'mscan_state' Documentation: networking: document ISO 15765-2 can: xilinx_can: Document driver description to list all supported IPs can: isotp: remove ISO 15675-2 specification version where possible ... ==================== Link: https://patch.msgid.link/20240621080201.305471-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
e9212f9dd1
@ -5,7 +5,7 @@ $id: http://devicetree.org/schemas/net/can/xilinx,can.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title:
|
||||
Xilinx Axi CAN/Zynq CANPS controller
|
||||
Xilinx CAN and CANFD controller
|
||||
|
||||
maintainers:
|
||||
- Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
|
||||
|
@ -19,6 +19,7 @@ Contents:
|
||||
caif/index
|
||||
ethtool-netlink
|
||||
ieee802154
|
||||
iso15765-2
|
||||
j1939
|
||||
kapi
|
||||
msg_zerocopy
|
||||
|
386
Documentation/networking/iso15765-2.rst
Normal file
386
Documentation/networking/iso15765-2.rst
Normal file
@ -0,0 +1,386 @@
|
||||
.. SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
|
||||
|
||||
====================
|
||||
ISO 15765-2 (ISO-TP)
|
||||
====================
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
ISO 15765-2, also known as ISO-TP, is a transport protocol specifically defined
|
||||
for diagnostic communication on CAN. It is widely used in the automotive
|
||||
industry, for example as the transport protocol for UDSonCAN (ISO 14229-3) or
|
||||
emission-related diagnostic services (ISO 15031-5).
|
||||
|
||||
ISO-TP can be used both on CAN CC (aka Classical CAN) and CAN FD (CAN with
|
||||
Flexible Datarate) based networks. It is also designed to be compatible with a
|
||||
CAN network using SAE J1939 as data link layer (however, this is not a
|
||||
requirement).
|
||||
|
||||
Specifications used
|
||||
-------------------
|
||||
|
||||
* ISO 15765-2:2024 : Road vehicles - Diagnostic communication over Controller
|
||||
Area Network (DoCAN). Part 2: Transport protocol and network layer services.
|
||||
|
||||
Addressing
|
||||
----------
|
||||
|
||||
In its simplest form, ISO-TP is based on two kinds of addressing modes for the
|
||||
nodes connected to the same network:
|
||||
|
||||
* physical addressing is implemented by two node-specific addresses and is used
|
||||
in 1-to-1 communication.
|
||||
|
||||
* functional addressing is implemented by one node-specific address and is used
|
||||
in 1-to-N communication.
|
||||
|
||||
Three different addressing formats can be employed:
|
||||
|
||||
* "normal" : each address is represented simply by a CAN ID.
|
||||
|
||||
* "extended": each address is represented by a CAN ID plus the first byte of
|
||||
the CAN payload; both the CAN ID and the byte inside the payload shall be
|
||||
different between two addresses.
|
||||
|
||||
* "mixed": each address is represented by a CAN ID plus the first byte of
|
||||
the CAN payload; the CAN ID is different between two addresses, but the
|
||||
additional byte is the same.
|
||||
|
||||
Transport protocol and associated frame types
|
||||
---------------------------------------------
|
||||
|
||||
When transmitting data using the ISO-TP protocol, the payload can either fit
|
||||
inside one single CAN message or not, also considering the overhead the protocol
|
||||
is generating and the optional extended addressing. In the first case, the data
|
||||
is transmitted at once using a so-called Single Frame (SF). In the second case,
|
||||
ISO-TP defines a multi-frame protocol, in which the sender provides (through a
|
||||
First Frame - FF) the PDU length which is to be transmitted and also asks for a
|
||||
Flow Control (FC) frame, which provides the maximum supported size of a macro
|
||||
data block (``blocksize``) and the minimum time between the single CAN messages
|
||||
composing such block (``stmin``). Once this information has been received, the
|
||||
sender starts to send frames containing fragments of the data payload (called
|
||||
Consecutive Frames - CF), stopping after every ``blocksize``-sized block to wait
|
||||
confirmation from the receiver which should then send another Flow Control
|
||||
frame to inform the sender about its availability to receive more data.
|
||||
|
||||
How to Use ISO-TP
|
||||
=================
|
||||
|
||||
As with others CAN protocols, the ISO-TP stack support is built into the
|
||||
Linux network subsystem for the CAN bus, aka. Linux-CAN or SocketCAN, and
|
||||
thus follows the same socket API.
|
||||
|
||||
Creation and basic usage of an ISO-TP socket
|
||||
--------------------------------------------
|
||||
|
||||
To use the ISO-TP stack, ``#include <linux/can/isotp.h>`` shall be used. A
|
||||
socket can then be created using the ``PF_CAN`` protocol family, the
|
||||
``SOCK_DGRAM`` type (as the underlying protocol is datagram-based by design)
|
||||
and the ``CAN_ISOTP`` protocol:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP);
|
||||
|
||||
After the socket has been successfully created, ``bind(2)`` shall be called to
|
||||
bind the socket to the desired CAN interface; to do so:
|
||||
|
||||
* a TX CAN ID shall be specified as part of the sockaddr supplied to the call
|
||||
itself.
|
||||
|
||||
* a RX CAN ID shall also be specified, unless broadcast flags have been set
|
||||
through socket option (explained below).
|
||||
|
||||
Once bound to an interface, the socket can be read from and written to using
|
||||
the usual ``read(2)`` and ``write(2)`` system calls, as well as ``send(2)``,
|
||||
``sendmsg(2)``, ``recv(2)`` and ``recvmsg(2)``.
|
||||
Unlike the CAN_RAW socket API, only the ISO-TP data field (the actual payload)
|
||||
is sent and received by the userspace application using these calls. The address
|
||||
information and the protocol information are automatically filled by the ISO-TP
|
||||
stack using the configuration supplied during socket creation. In the same way,
|
||||
the stack will use the transport mechanism when required (i.e., when the size
|
||||
of the data payload exceeds the MTU of the underlying CAN bus).
|
||||
|
||||
The sockaddr structure used for SocketCAN has extensions for use with ISO-TP,
|
||||
as specified below:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct sockaddr_can {
|
||||
sa_family_t can_family;
|
||||
int can_ifindex;
|
||||
union {
|
||||
struct { canid_t rx_id, tx_id; } tp;
|
||||
...
|
||||
} can_addr;
|
||||
}
|
||||
|
||||
* ``can_family`` and ``can_ifindex`` serve the same purpose as for other
|
||||
SocketCAN sockets.
|
||||
|
||||
* ``can_addr.tp.rx_id`` specifies the receive (RX) CAN ID and will be used as
|
||||
a RX filter.
|
||||
|
||||
* ``can_addr.tp.tx_id`` specifies the transmit (TX) CAN ID
|
||||
|
||||
ISO-TP socket options
|
||||
---------------------
|
||||
|
||||
When creating an ISO-TP socket, reasonable defaults are set. Some options can
|
||||
be modified with ``setsockopt(2)`` and/or read back with ``getsockopt(2)``.
|
||||
|
||||
General options
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
General socket options can be passed using the ``CAN_ISOTP_OPTS`` optname:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct can_isotp_options opts;
|
||||
ret = setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts))
|
||||
|
||||
where the ``can_isotp_options`` structure has the following contents:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct can_isotp_options {
|
||||
u32 flags;
|
||||
u32 frame_txtime;
|
||||
u8 ext_address;
|
||||
u8 txpad_content;
|
||||
u8 rxpad_content;
|
||||
u8 rx_ext_address;
|
||||
};
|
||||
|
||||
* ``flags``: modifiers to be applied to the default behaviour of the ISO-TP
|
||||
stack. Following flags are available:
|
||||
|
||||
* ``CAN_ISOTP_LISTEN_MODE``: listen only (do not send FC frames); normally
|
||||
used as a testing feature.
|
||||
|
||||
* ``CAN_ISOTP_EXTEND_ADDR``: use the byte specified in ``ext_address`` as an
|
||||
additional address component. This enables the "mixed" addressing format if
|
||||
used alone, or the "extended" addressing format if used in conjunction with
|
||||
``CAN_ISOTP_RX_EXT_ADDR``.
|
||||
|
||||
* ``CAN_ISOTP_TX_PADDING``: enable padding for transmitted frames, using
|
||||
``txpad_content`` as value for the padding bytes.
|
||||
|
||||
* ``CAN_ISOTP_RX_PADDING``: enable padding for the received frames, using
|
||||
``rxpad_content`` as value for the padding bytes.
|
||||
|
||||
* ``CAN_ISOTP_CHK_PAD_LEN``: check for correct padding length on the received
|
||||
frames.
|
||||
|
||||
* ``CAN_ISOTP_CHK_PAD_DATA``: check padding bytes on the received frames
|
||||
against ``rxpad_content``; if ``CAN_ISOTP_RX_PADDING`` is not specified,
|
||||
this flag is ignored.
|
||||
|
||||
* ``CAN_ISOTP_HALF_DUPLEX``: force ISO-TP socket in half duplex mode
|
||||
(that is, transport mechanism can only be incoming or outgoing at the same
|
||||
time, not both).
|
||||
|
||||
* ``CAN_ISOTP_FORCE_TXSTMIN``: ignore stmin from received FC; normally
|
||||
used as a testing feature.
|
||||
|
||||
* ``CAN_ISOTP_FORCE_RXSTMIN``: ignore CFs depending on rx stmin; normally
|
||||
used as a testing feature.
|
||||
|
||||
* ``CAN_ISOTP_RX_EXT_ADDR``: use ``rx_ext_address`` instead of ``ext_address``
|
||||
as extended addressing byte on the reception path. If used in conjunction
|
||||
with ``CAN_ISOTP_EXTEND_ADDR``, this flag effectively enables the "extended"
|
||||
addressing format.
|
||||
|
||||
* ``CAN_ISOTP_WAIT_TX_DONE``: wait until the frame is sent before returning
|
||||
from ``write(2)`` and ``send(2)`` calls (i.e., blocking write operations).
|
||||
|
||||
* ``CAN_ISOTP_SF_BROADCAST``: use 1-to-N functional addressing (cannot be
|
||||
specified alongside ``CAN_ISOTP_CF_BROADCAST``).
|
||||
|
||||
* ``CAN_ISOTP_CF_BROADCAST``: use 1-to-N transmission without flow control
|
||||
(cannot be specified alongside ``CAN_ISOTP_SF_BROADCAST``).
|
||||
NOTE: this is not covered by the ISO 15765-2 standard.
|
||||
|
||||
* ``CAN_ISOTP_DYN_FC_PARMS``: enable dynamic update of flow control
|
||||
parameters.
|
||||
|
||||
* ``frame_txtime``: frame transmission time (defined as N_As/N_Ar inside the
|
||||
ISO standard); if ``0``, the default (or the last set value) is used.
|
||||
To set the transmission time to ``0``, the ``CAN_ISOTP_FRAME_TXTIME_ZERO``
|
||||
macro (equal to 0xFFFFFFFF) shall be used.
|
||||
|
||||
* ``ext_address``: extended addressing byte, used if the
|
||||
``CAN_ISOTP_EXTEND_ADDR`` flag is specified.
|
||||
|
||||
* ``txpad_content``: byte used as padding value for transmitted frames.
|
||||
|
||||
* ``rxpad_content``: byte used as padding value for received frames.
|
||||
|
||||
* ``rx_ext_address``: extended addressing byte for the reception path, used if
|
||||
the ``CAN_ISOTP_RX_EXT_ADDR`` flag is specified.
|
||||
|
||||
Flow Control options
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Flow Control (FC) options can be passed using the ``CAN_ISOTP_RECV_FC`` optname
|
||||
to provide the communication parameters for receiving ISO-TP PDUs.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct can_isotp_fc_options fc_opts;
|
||||
ret = setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fc_opts, sizeof(fc_opts));
|
||||
|
||||
where the ``can_isotp_fc_options`` structure has the following contents:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct can_isotp_options {
|
||||
u8 bs;
|
||||
u8 stmin;
|
||||
u8 wftmax;
|
||||
};
|
||||
|
||||
* ``bs``: blocksize provided in flow control frames.
|
||||
|
||||
* ``stmin``: minimum separation time provided in flow control frames; can
|
||||
have the following values (others are reserved):
|
||||
|
||||
* 0x00 - 0x7F : 0 - 127 ms
|
||||
|
||||
* 0xF1 - 0xF9 : 100 us - 900 us
|
||||
|
||||
* ``wftmax``: maximum number of wait frames provided in flow control frames.
|
||||
|
||||
Link Layer options
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Link Layer (LL) options can be passed using the ``CAN_ISOTP_LL_OPTS`` optname:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct can_isotp_ll_options ll_opts;
|
||||
ret = setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &ll_opts, sizeof(ll_opts));
|
||||
|
||||
where the ``can_isotp_ll_options`` structure has the following contents:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
struct can_isotp_ll_options {
|
||||
u8 mtu;
|
||||
u8 tx_dl;
|
||||
u8 tx_flags;
|
||||
};
|
||||
|
||||
* ``mtu``: generated and accepted CAN frame type, can be equal to ``CAN_MTU``
|
||||
for classical CAN frames or ``CANFD_MTU`` for CAN FD frames.
|
||||
|
||||
* ``tx_dl``: maximum payload length for transmitted frames, can have one value
|
||||
among: 8, 12, 16, 20, 24, 32, 48, 64. Values above 8 only apply to CAN FD
|
||||
traffic (i.e.: ``mtu = CANFD_MTU``).
|
||||
|
||||
* ``tx_flags``: flags set into ``struct canfd_frame.flags`` at frame creation.
|
||||
Only applies to CAN FD traffic (i.e.: ``mtu = CANFD_MTU``).
|
||||
|
||||
Transmission stmin
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The transmission minimum separation time (stmin) can be forced using the
|
||||
``CAN_ISOTP_TX_STMIN`` optname and providing an stmin value in microseconds as
|
||||
a 32bit unsigned integer; this will overwrite the value sent by the receiver in
|
||||
flow control frames:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
uint32_t stmin;
|
||||
ret = setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_TX_STMIN, &stmin, sizeof(stmin));
|
||||
|
||||
Reception stmin
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The reception minimum separation time (stmin) can be forced using the
|
||||
``CAN_ISOTP_RX_STMIN`` optname and providing an stmin value in microseconds as
|
||||
a 32bit unsigned integer; received Consecutive Frames (CF) which timestamps
|
||||
differ less than this value will be ignored:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
uint32_t stmin;
|
||||
ret = setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RX_STMIN, &stmin, sizeof(stmin));
|
||||
|
||||
Multi-frame transport support
|
||||
-----------------------------
|
||||
|
||||
The ISO-TP stack contained inside the Linux kernel supports the multi-frame
|
||||
transport mechanism defined by the standard, with the following constraints:
|
||||
|
||||
* the maximum size of a PDU is defined by a module parameter, with an hard
|
||||
limit imposed at build time.
|
||||
|
||||
* when a transmission is in progress, subsequent calls to ``write(2)`` will
|
||||
block, while calls to ``send(2)`` will either block or fail depending on the
|
||||
presence of the ``MSG_DONTWAIT`` flag.
|
||||
|
||||
* no support is present for sending "wait frames": whether a PDU can be fully
|
||||
received or not is decided when the First Frame is received.
|
||||
|
||||
Errors
|
||||
------
|
||||
|
||||
Following errors are reported to userspace:
|
||||
|
||||
RX path errors
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
============ ===============================================================
|
||||
-ETIMEDOUT timeout of data reception
|
||||
-EILSEQ sequence number mismatch during a multi-frame reception
|
||||
-EBADMSG data reception with wrong padding
|
||||
============ ===============================================================
|
||||
|
||||
TX path errors
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
========== =================================================================
|
||||
-ECOMM flow control reception timeout
|
||||
-EMSGSIZE flow control reception overflow
|
||||
-EBADMSG flow control reception with wrong layout/padding
|
||||
========== =================================================================
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Basic node example
|
||||
------------------
|
||||
|
||||
Following example implements a node using "normal" physical addressing, with
|
||||
RX ID equal to 0x18DAF142 and a TX ID equal to 0x18DA42F1. All options are left
|
||||
to their default.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
int s;
|
||||
struct sockaddr_can addr;
|
||||
int ret;
|
||||
|
||||
s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP);
|
||||
if (s < 0)
|
||||
exit(1);
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = if_nametoindex("can0");
|
||||
addr.tp.tx_id = 0x18DA42F1 | CAN_EFF_FLAG;
|
||||
addr.tp.rx_id = 0x18DAF142 | CAN_EFF_FLAG;
|
||||
|
||||
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (ret < 0)
|
||||
exit(1);
|
||||
|
||||
/* Data can now be received using read(s, ...) and sent using write(s, ...) */
|
||||
|
||||
Additional examples
|
||||
-------------------
|
||||
|
||||
More complete (and complex) examples can be found inside the ``isotp*`` userland
|
||||
tools, distributed as part of the ``can-utils`` utilities at:
|
||||
https://github.com/linux-can/can-utils
|
@ -4842,6 +4842,7 @@ W: https://github.com/linux-can
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
|
||||
F: Documentation/networking/can.rst
|
||||
F: Documentation/networking/iso15765-2.rst
|
||||
F: include/linux/can/can-ml.h
|
||||
F: include/linux/can/core.h
|
||||
F: include/linux/can/skb.h
|
||||
|
@ -187,9 +187,8 @@ config CAN_SLCAN
|
||||
slcand) can be found in the can-utils at the linux-can project, see
|
||||
https://github.com/linux-can/can-utils for details.
|
||||
|
||||
The slcan driver supports up to 10 CAN netdevices by default which
|
||||
can be changed by the 'maxdev=xx' module option. This driver can
|
||||
also be built as a module. If so, the module will be called slcan.
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called slcan.
|
||||
|
||||
config CAN_SUN4I
|
||||
tristate "Allwinner A10 CAN controller"
|
||||
|
@ -29,10 +29,10 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
|
||||
#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17U
|
||||
#define KVASER_PCIEFD_MAX_CAN_CHANNELS 8UL
|
||||
#define KVASER_PCIEFD_DMA_COUNT 2U
|
||||
|
||||
#define KVASER_PCIEFD_DMA_SIZE (4U * 1024U)
|
||||
|
||||
#define KVASER_PCIEFD_VENDOR 0x1a07
|
||||
|
||||
/* Altera based devices */
|
||||
#define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d
|
||||
#define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e
|
||||
@ -550,7 +550,7 @@ static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can)
|
||||
spin_unlock_irqrestore(&can->lock, irq);
|
||||
}
|
||||
|
||||
static void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
|
||||
static inline void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
|
||||
{
|
||||
u32 msk;
|
||||
|
||||
@ -711,17 +711,17 @@ static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can)
|
||||
|
||||
static int kvaser_pciefd_open(struct net_device *netdev)
|
||||
{
|
||||
int err;
|
||||
int ret;
|
||||
struct kvaser_pciefd_can *can = netdev_priv(netdev);
|
||||
|
||||
err = open_candev(netdev);
|
||||
if (err)
|
||||
return err;
|
||||
ret = open_candev(netdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
err = kvaser_pciefd_bus_on(can);
|
||||
if (err) {
|
||||
ret = kvaser_pciefd_bus_on(can);
|
||||
if (ret) {
|
||||
close_candev(netdev);
|
||||
return err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1032,15 +1032,15 @@ static int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pcie->nr_channels; i++) {
|
||||
int err = register_candev(pcie->can[i]->can.dev);
|
||||
int ret = register_candev(pcie->can[i]->can.dev);
|
||||
|
||||
if (err) {
|
||||
if (ret) {
|
||||
int j;
|
||||
|
||||
/* Unregister all successfully registered devices. */
|
||||
for (j = 0; j < i; j++)
|
||||
unregister_candev(pcie->can[j]->can.dev);
|
||||
return err;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1619,7 +1619,7 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
|
||||
/* Position does not point to the end of the package,
|
||||
* corrupted packet size?
|
||||
*/
|
||||
if ((*start_pos + size) != pos)
|
||||
if (unlikely((*start_pos + size) != pos))
|
||||
return -EIO;
|
||||
|
||||
/* Point to the next packet header, if any */
|
||||
@ -1640,31 +1640,24 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
|
||||
static u32 kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
|
||||
{
|
||||
u32 irq = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
|
||||
|
||||
if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) {
|
||||
if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0)
|
||||
kvaser_pciefd_read_buffer(pcie, 0);
|
||||
/* Reset DMA buffer 0 */
|
||||
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
|
||||
KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
|
||||
}
|
||||
|
||||
if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) {
|
||||
if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1)
|
||||
kvaser_pciefd_read_buffer(pcie, 1);
|
||||
/* Reset DMA buffer 1 */
|
||||
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
|
||||
KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
|
||||
}
|
||||
|
||||
if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 ||
|
||||
irq & KVASER_PCIEFD_SRB_IRQ_DOF1 ||
|
||||
irq & KVASER_PCIEFD_SRB_IRQ_DUF0 ||
|
||||
irq & KVASER_PCIEFD_SRB_IRQ_DUF1)
|
||||
if (unlikely(irq & KVASER_PCIEFD_SRB_IRQ_DOF0 ||
|
||||
irq & KVASER_PCIEFD_SRB_IRQ_DOF1 ||
|
||||
irq & KVASER_PCIEFD_SRB_IRQ_DUF0 ||
|
||||
irq & KVASER_PCIEFD_SRB_IRQ_DUF1))
|
||||
dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq);
|
||||
|
||||
iowrite32(irq, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
|
||||
return irq;
|
||||
}
|
||||
|
||||
static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
|
||||
@ -1691,27 +1684,33 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
|
||||
{
|
||||
struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev;
|
||||
const struct kvaser_pciefd_irq_mask *irq_mask = pcie->driver_data->irq_mask;
|
||||
u32 board_irq = ioread32(KVASER_PCIEFD_PCI_IRQ_ADDR(pcie));
|
||||
u32 pci_irq = ioread32(KVASER_PCIEFD_PCI_IRQ_ADDR(pcie));
|
||||
u32 srb_irq = 0;
|
||||
int i;
|
||||
|
||||
if (!(board_irq & irq_mask->all))
|
||||
if (!(pci_irq & irq_mask->all))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (board_irq & irq_mask->kcan_rx0)
|
||||
kvaser_pciefd_receive_irq(pcie);
|
||||
if (pci_irq & irq_mask->kcan_rx0)
|
||||
srb_irq = kvaser_pciefd_receive_irq(pcie);
|
||||
|
||||
for (i = 0; i < pcie->nr_channels; i++) {
|
||||
if (!pcie->can[i]) {
|
||||
dev_err(&pcie->pci->dev,
|
||||
"IRQ mask points to unallocated controller\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that mask matches channel (i) IRQ mask */
|
||||
if (board_irq & irq_mask->kcan_tx[i])
|
||||
if (pci_irq & irq_mask->kcan_tx[i])
|
||||
kvaser_pciefd_transmit_irq(pcie->can[i]);
|
||||
}
|
||||
|
||||
if (srb_irq & KVASER_PCIEFD_SRB_IRQ_DPD0) {
|
||||
/* Reset DMA buffer 0, may trigger new interrupt */
|
||||
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
|
||||
KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
|
||||
}
|
||||
|
||||
if (srb_irq & KVASER_PCIEFD_SRB_IRQ_DPD1) {
|
||||
/* Reset DMA buffer 1, may trigger new interrupt */
|
||||
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
|
||||
KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -1733,7 +1732,7 @@ static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)
|
||||
static int kvaser_pciefd_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
int err;
|
||||
int ret;
|
||||
struct kvaser_pciefd *pcie;
|
||||
const struct kvaser_pciefd_irq_mask *irq_mask;
|
||||
void __iomem *irq_en_base;
|
||||
@ -1747,39 +1746,52 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
|
||||
pcie->driver_data = (const struct kvaser_pciefd_driver_data *)id->driver_data;
|
||||
irq_mask = pcie->driver_data->irq_mask;
|
||||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
err = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME);
|
||||
if (err)
|
||||
ret = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME);
|
||||
if (ret)
|
||||
goto err_disable_pci;
|
||||
|
||||
pcie->reg_base = pci_iomap(pdev, 0, 0);
|
||||
if (!pcie->reg_base) {
|
||||
err = -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto err_release_regions;
|
||||
}
|
||||
|
||||
err = kvaser_pciefd_setup_board(pcie);
|
||||
if (err)
|
||||
ret = kvaser_pciefd_setup_board(pcie);
|
||||
if (ret)
|
||||
goto err_pci_iounmap;
|
||||
|
||||
err = kvaser_pciefd_setup_dma(pcie);
|
||||
if (err)
|
||||
ret = kvaser_pciefd_setup_dma(pcie);
|
||||
if (ret)
|
||||
goto err_pci_iounmap;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
err = kvaser_pciefd_setup_can_ctrls(pcie);
|
||||
if (err)
|
||||
ret = kvaser_pciefd_setup_can_ctrls(pcie);
|
||||
if (ret)
|
||||
goto err_teardown_can_ctrls;
|
||||
|
||||
err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
|
||||
ret = pci_alloc_irq_vectors(pcie->pci, 1, 1, PCI_IRQ_INTX | PCI_IRQ_MSI);
|
||||
if (ret < 0) {
|
||||
dev_err(&pcie->pci->dev, "Failed to allocate IRQ vectors.\n");
|
||||
goto err_teardown_can_ctrls;
|
||||
}
|
||||
|
||||
ret = pci_irq_vector(pcie->pci, 0);
|
||||
if (ret < 0)
|
||||
goto err_pci_free_irq_vectors;
|
||||
|
||||
pcie->pci->irq = ret;
|
||||
|
||||
ret = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
|
||||
IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
|
||||
if (err)
|
||||
goto err_teardown_can_ctrls;
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pcie->pci->dev, "Failed to request IRQ %d\n", pcie->pci->irq);
|
||||
goto err_pci_free_irq_vectors;
|
||||
}
|
||||
iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1,
|
||||
KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
|
||||
|
||||
@ -1797,8 +1809,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
|
||||
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
|
||||
KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
|
||||
|
||||
err = kvaser_pciefd_reg_candev(pcie);
|
||||
if (err)
|
||||
ret = kvaser_pciefd_reg_candev(pcie);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
return 0;
|
||||
@ -1808,6 +1820,9 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
|
||||
iowrite32(0, irq_en_base);
|
||||
free_irq(pcie->pci->irq, pcie);
|
||||
|
||||
err_pci_free_irq_vectors:
|
||||
pci_free_irq_vectors(pcie->pci);
|
||||
|
||||
err_teardown_can_ctrls:
|
||||
kvaser_pciefd_teardown_can_ctrls(pcie);
|
||||
iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
|
||||
@ -1822,7 +1837,7 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
|
||||
err_disable_pci:
|
||||
pci_disable_device(pdev);
|
||||
|
||||
return err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie)
|
||||
@ -1853,7 +1868,7 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev)
|
||||
iowrite32(0, KVASER_PCIEFD_PCI_IEN_ADDR(pcie));
|
||||
|
||||
free_irq(pcie->pci->irq, pcie);
|
||||
|
||||
pci_free_irq_vectors(pcie->pci);
|
||||
pci_iounmap(pdev, pcie->reg_base);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
|
@ -379,38 +379,72 @@ m_can_txe_fifo_read(struct m_can_classdev *cdev, u32 fgi, u32 offset, u32 *val)
|
||||
return cdev->ops->read_fifo(cdev, addr_offset, val, 1);
|
||||
}
|
||||
|
||||
static void m_can_config_endisable(struct m_can_classdev *cdev, bool enable)
|
||||
static int m_can_cccr_update_bits(struct m_can_classdev *cdev, u32 mask, u32 val)
|
||||
{
|
||||
u32 cccr = m_can_read(cdev, M_CAN_CCCR);
|
||||
u32 timeout = 10;
|
||||
u32 val = 0;
|
||||
u32 val_before = m_can_read(cdev, M_CAN_CCCR);
|
||||
u32 val_after = (val_before & ~mask) | val;
|
||||
size_t tries = 10;
|
||||
|
||||
/* Clear the Clock stop request if it was set */
|
||||
if (cccr & CCCR_CSR)
|
||||
cccr &= ~CCCR_CSR;
|
||||
|
||||
if (enable) {
|
||||
/* enable m_can configuration */
|
||||
m_can_write(cdev, M_CAN_CCCR, cccr | CCCR_INIT);
|
||||
udelay(5);
|
||||
/* CCCR.CCE can only be set/reset while CCCR.INIT = '1' */
|
||||
m_can_write(cdev, M_CAN_CCCR, cccr | CCCR_INIT | CCCR_CCE);
|
||||
} else {
|
||||
m_can_write(cdev, M_CAN_CCCR, cccr & ~(CCCR_INIT | CCCR_CCE));
|
||||
if (!(mask & CCCR_INIT) && !(val_before & CCCR_INIT)) {
|
||||
dev_err(cdev->dev,
|
||||
"refusing to configure device when in normal mode\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* there's a delay for module initialization */
|
||||
if (enable)
|
||||
val = CCCR_INIT | CCCR_CCE;
|
||||
/* The chip should be in standby mode when changing the CCCR register,
|
||||
* and some chips set the CSR and CSA bits when in standby. Furthermore,
|
||||
* the CSR and CSA bits should be written as zeros, even when they read
|
||||
* ones.
|
||||
*/
|
||||
val_after &= ~(CCCR_CSR | CCCR_CSA);
|
||||
|
||||
while ((m_can_read(cdev, M_CAN_CCCR) & (CCCR_INIT | CCCR_CCE)) != val) {
|
||||
if (timeout == 0) {
|
||||
netdev_warn(cdev->net, "Failed to init module\n");
|
||||
return;
|
||||
}
|
||||
timeout--;
|
||||
udelay(1);
|
||||
while (tries--) {
|
||||
u32 val_read;
|
||||
|
||||
/* Write the desired value in each try, as setting some bits in
|
||||
* the CCCR register require other bits to be set first. E.g.
|
||||
* setting the NISO bit requires setting the CCE bit first.
|
||||
*/
|
||||
m_can_write(cdev, M_CAN_CCCR, val_after);
|
||||
|
||||
val_read = m_can_read(cdev, M_CAN_CCCR) & ~(CCCR_CSR | CCCR_CSA);
|
||||
|
||||
if (val_read == val_after)
|
||||
return 0;
|
||||
|
||||
usleep_range(1, 5);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int m_can_config_enable(struct m_can_classdev *cdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* CCCR_INIT must be set in order to set CCCR_CCE, but access to
|
||||
* configuration registers should only be enabled when in standby mode,
|
||||
* where CCCR_INIT is always set.
|
||||
*/
|
||||
err = m_can_cccr_update_bits(cdev, CCCR_CCE, CCCR_CCE);
|
||||
if (err)
|
||||
netdev_err(cdev->net, "failed to enable configuration mode\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int m_can_config_disable(struct m_can_classdev *cdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Only clear CCCR_CCE, since CCCR_INIT cannot be cleared while in
|
||||
* standby mode
|
||||
*/
|
||||
err = m_can_cccr_update_bits(cdev, CCCR_CCE, 0);
|
||||
if (err)
|
||||
netdev_err(cdev->net, "failed to disable configuration registers\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void m_can_interrupt_enable(struct m_can_classdev *cdev, u32 interrupts)
|
||||
@ -1403,7 +1437,9 @@ static int m_can_chip_config(struct net_device *dev)
|
||||
interrupts &= ~(IR_ARA | IR_ELO | IR_DRX | IR_TEFF | IR_TFE | IR_TCF |
|
||||
IR_HPM | IR_RF1F | IR_RF1W | IR_RF1N | IR_RF0F);
|
||||
|
||||
m_can_config_endisable(cdev, true);
|
||||
err = m_can_config_enable(cdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* RX Buffer/FIFO Element Size 64 bytes data field */
|
||||
m_can_write(cdev, M_CAN_RXESC,
|
||||
@ -1521,7 +1557,9 @@ static int m_can_chip_config(struct net_device *dev)
|
||||
FIELD_PREP(TSCC_TCP_MASK, 0xf) |
|
||||
FIELD_PREP(TSCC_TSS_MASK, TSCC_TSS_INTERNAL));
|
||||
|
||||
m_can_config_endisable(cdev, false);
|
||||
err = m_can_config_disable(cdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (cdev->ops->init)
|
||||
cdev->ops->init(cdev);
|
||||
@ -1550,7 +1588,11 @@ static int m_can_start(struct net_device *dev)
|
||||
cdev->tx_fifo_putidx = FIELD_GET(TXFQS_TFQPI_MASK,
|
||||
m_can_read(cdev, M_CAN_TXFQS));
|
||||
|
||||
return 0;
|
||||
ret = m_can_cccr_update_bits(cdev, CCCR_INIT, 0);
|
||||
if (ret)
|
||||
netdev_err(dev, "failed to enter normal mode\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m_can_set_mode(struct net_device *dev, enum can_mode mode)
|
||||
@ -1599,43 +1641,37 @@ static int m_can_check_core_release(struct m_can_classdev *cdev)
|
||||
}
|
||||
|
||||
/* Selectable Non ISO support only in version 3.2.x
|
||||
* This function checks if the bit is writable.
|
||||
* Return 1 if the bit is writable, 0 if it is not, or negative on error.
|
||||
*/
|
||||
static bool m_can_niso_supported(struct m_can_classdev *cdev)
|
||||
static int m_can_niso_supported(struct m_can_classdev *cdev)
|
||||
{
|
||||
u32 cccr_reg, cccr_poll = 0;
|
||||
int niso_timeout = -ETIMEDOUT;
|
||||
int i;
|
||||
int ret, niso;
|
||||
|
||||
m_can_config_endisable(cdev, true);
|
||||
cccr_reg = m_can_read(cdev, M_CAN_CCCR);
|
||||
cccr_reg |= CCCR_NISO;
|
||||
m_can_write(cdev, M_CAN_CCCR, cccr_reg);
|
||||
ret = m_can_config_enable(cdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i <= 10; i++) {
|
||||
cccr_poll = m_can_read(cdev, M_CAN_CCCR);
|
||||
if (cccr_poll == cccr_reg) {
|
||||
niso_timeout = 0;
|
||||
break;
|
||||
}
|
||||
/* First try to set the NISO bit. */
|
||||
niso = m_can_cccr_update_bits(cdev, CCCR_NISO, CCCR_NISO);
|
||||
|
||||
usleep_range(1, 5);
|
||||
/* Then clear the it again. */
|
||||
ret = m_can_cccr_update_bits(cdev, CCCR_NISO, 0);
|
||||
if (ret) {
|
||||
dev_err(cdev->dev, "failed to revert the NON-ISO bit in CCCR\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Clear NISO */
|
||||
cccr_reg &= ~(CCCR_NISO);
|
||||
m_can_write(cdev, M_CAN_CCCR, cccr_reg);
|
||||
ret = m_can_config_disable(cdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
m_can_config_endisable(cdev, false);
|
||||
|
||||
/* return false if time out (-ETIMEDOUT), else return true */
|
||||
return !niso_timeout;
|
||||
return niso == 0;
|
||||
}
|
||||
|
||||
static int m_can_dev_setup(struct m_can_classdev *cdev)
|
||||
{
|
||||
struct net_device *dev = cdev->net;
|
||||
int m_can_version, err;
|
||||
int m_can_version, err, niso;
|
||||
|
||||
m_can_version = m_can_check_core_release(cdev);
|
||||
/* return if unsupported version */
|
||||
@ -1684,9 +1720,11 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
|
||||
cdev->can.bittiming_const = &m_can_bittiming_const_31X;
|
||||
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
|
||||
|
||||
cdev->can.ctrlmode_supported |=
|
||||
(m_can_niso_supported(cdev) ?
|
||||
CAN_CTRLMODE_FD_NON_ISO : 0);
|
||||
niso = m_can_niso_supported(cdev);
|
||||
if (niso < 0)
|
||||
return niso;
|
||||
if (niso)
|
||||
cdev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO;
|
||||
break;
|
||||
default:
|
||||
dev_err(cdev->dev, "Unsupported version number: %2d",
|
||||
@ -1694,21 +1732,26 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cdev->ops->init)
|
||||
cdev->ops->init(cdev);
|
||||
|
||||
return 0;
|
||||
/* Forcing standby mode should be redundant, as the chip should be in
|
||||
* standby after a reset. Write the INIT bit anyways, should the chip
|
||||
* be configured by previous stage.
|
||||
*/
|
||||
return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
|
||||
}
|
||||
|
||||
static void m_can_stop(struct net_device *dev)
|
||||
{
|
||||
struct m_can_classdev *cdev = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
/* disable all interrupts */
|
||||
m_can_disable_all_interrupts(cdev);
|
||||
|
||||
/* Set init mode to disengage from the network */
|
||||
m_can_config_endisable(cdev, true);
|
||||
ret = m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
|
||||
if (ret)
|
||||
netdev_err(dev, "failed to enter standby mode: %pe\n",
|
||||
ERR_PTR(ret));
|
||||
|
||||
/* set the state as STOPPED */
|
||||
cdev->can.state = CAN_STATE_STOPPED;
|
||||
|
@ -453,10 +453,17 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
|
||||
goto out_power;
|
||||
}
|
||||
|
||||
ret = tcan4x5x_init(mcan_class);
|
||||
tcan4x5x_check_wake(priv);
|
||||
|
||||
ret = tcan4x5x_write_tcan_reg(mcan_class, TCAN4X5X_INT_EN, 0);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "tcan initialization failed %pe\n",
|
||||
ERR_PTR(ret));
|
||||
dev_err(&spi->dev, "Disabling interrupts failed %pe\n", ERR_PTR(ret));
|
||||
goto out_power;
|
||||
}
|
||||
|
||||
ret = tcan4x5x_clear_interrupts(mcan_class);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Clearing interrupts failed %pe\n", ERR_PTR(ret));
|
||||
goto out_power;
|
||||
}
|
||||
|
||||
|
@ -34,12 +34,6 @@ static const struct can_bittiming_const mscan_bittiming_const = {
|
||||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
struct mscan_state {
|
||||
u8 mode;
|
||||
u8 canrier;
|
||||
u8 cantier;
|
||||
};
|
||||
|
||||
static enum can_state state_map[] = {
|
||||
CAN_STATE_ERROR_ACTIVE,
|
||||
CAN_STATE_ERROR_WARNING,
|
||||
|
@ -122,7 +122,6 @@ struct plx_pci_card {
|
||||
#define TEWS_PCI_VENDOR_ID 0x1498
|
||||
#define TEWS_PCI_DEVICE_ID_TMPC810 0x032A
|
||||
|
||||
#define CTI_PCI_VENDOR_ID 0x12c4
|
||||
#define CTI_PCI_DEVICE_ID_CRG001 0x0900
|
||||
|
||||
#define MOXA_PCI_VENDOR_ID 0x1393
|
||||
@ -358,7 +357,7 @@ static const struct pci_device_id plx_pci_tbl[] = {
|
||||
{
|
||||
/* Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card */
|
||||
PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
|
||||
CTI_PCI_VENDOR_ID, CTI_PCI_DEVICE_ID_CRG001,
|
||||
PCI_SUBVENDOR_ID_CONNECT_TECH, CTI_PCI_DEVICE_ID_CRG001,
|
||||
0, 0,
|
||||
(kernel_ulong_t)&plx_pci_card_info_cti
|
||||
},
|
||||
|
@ -830,7 +830,6 @@ static int hi3110_can_probe(struct spi_device *spi)
|
||||
struct device *dev = &spi->dev;
|
||||
struct net_device *net;
|
||||
struct hi3110_priv *priv;
|
||||
const void *match;
|
||||
struct clk *clk;
|
||||
u32 freq;
|
||||
int ret;
|
||||
@ -874,11 +873,7 @@ static int hi3110_can_probe(struct spi_device *spi)
|
||||
CAN_CTRLMODE_LISTENONLY |
|
||||
CAN_CTRLMODE_BERR_REPORTING;
|
||||
|
||||
match = device_get_match_data(dev);
|
||||
if (match)
|
||||
priv->model = (enum hi3110_model)(uintptr_t)match;
|
||||
else
|
||||
priv->model = spi_get_device_id(spi)->driver_data;
|
||||
priv->model = (enum hi3110_model)(uintptr_t)spi_get_device_match_data(spi);
|
||||
priv->net = net;
|
||||
priv->clk = clk;
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
@ -482,9 +481,9 @@ static int mcp251x_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
if (mcp251x_gpio_is_input(offset))
|
||||
return GPIOF_DIR_IN;
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIOF_DIR_OUT;
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int mcp251x_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
@ -1301,7 +1300,6 @@ MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
|
||||
|
||||
static int mcp251x_can_probe(struct spi_device *spi)
|
||||
{
|
||||
const void *match = device_get_match_data(&spi->dev);
|
||||
struct net_device *net;
|
||||
struct mcp251x_priv *priv;
|
||||
struct clk *clk;
|
||||
@ -1339,10 +1337,7 @@ static int mcp251x_can_probe(struct spi_device *spi)
|
||||
priv->can.clock.freq = freq / 2;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
|
||||
CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
|
||||
if (match)
|
||||
priv->model = (enum mcp251x_model)(uintptr_t)match;
|
||||
else
|
||||
priv->model = spi_get_device_id(spi)->driver_data;
|
||||
priv->model = (enum mcp251x_model)(uintptr_t)spi_get_device_match_data(spi);
|
||||
priv->net = net;
|
||||
priv->clk = clk;
|
||||
|
||||
|
@ -1989,7 +1989,6 @@ MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table);
|
||||
|
||||
static int mcp251xfd_probe(struct spi_device *spi)
|
||||
{
|
||||
const void *match;
|
||||
struct net_device *ndev;
|
||||
struct mcp251xfd_priv *priv;
|
||||
struct gpio_desc *rx_int;
|
||||
@ -2081,13 +2080,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
|
||||
priv->pll_enable = pll_enable;
|
||||
priv->reg_vdd = reg_vdd;
|
||||
priv->reg_xceiver = reg_xceiver;
|
||||
|
||||
match = device_get_match_data(&spi->dev);
|
||||
if (match)
|
||||
priv->devtype_data = *(struct mcp251xfd_devtype_data *)match;
|
||||
else
|
||||
priv->devtype_data = *(struct mcp251xfd_devtype_data *)
|
||||
spi_get_device_id(spi)->driver_data;
|
||||
priv->devtype_data = *(struct mcp251xfd_devtype_data *)spi_get_device_match_data(spi);
|
||||
|
||||
/* Errata Reference:
|
||||
* mcp2517fd: DS80000792C 5., mcp2518fd: DS80000789C 4.
|
||||
|
@ -91,6 +91,7 @@ config CAN_KVASER_USB
|
||||
- Kvaser Leaf Light R v2
|
||||
- Kvaser Mini PCI Express HS
|
||||
- Kvaser Mini PCI Express 2xHS
|
||||
- Kvaser Mini PCIe 1xCAN
|
||||
- Kvaser USBcan Light 2xHS
|
||||
- Kvaser USBcan II HS/HS
|
||||
- Kvaser USBcan II HS/LS
|
||||
@ -111,12 +112,14 @@ config CAN_KVASER_USB
|
||||
- Kvaser USBcan Light 4xHS
|
||||
- Kvaser USBcan Pro 2xHS v2
|
||||
- Kvaser USBcan Pro 4xHS
|
||||
- Kvaser USBcan Pro 5xCAN
|
||||
- Kvaser USBcan Pro 5xHS
|
||||
- Kvaser U100
|
||||
- Kvaser U100P
|
||||
- Kvaser U100S
|
||||
- ATI Memorator Pro 2xHS v2
|
||||
- ATI USBcan Pro 2xHS v2
|
||||
- Vining 800
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
@ -89,6 +89,9 @@
|
||||
#define USB_HYBRID_CANLIN_PRODUCT_ID 0x0115
|
||||
#define USB_HYBRID_PRO_CANLIN_PRODUCT_ID 0x0116
|
||||
#define USB_LEAF_V3_PRODUCT_ID 0x0117
|
||||
#define USB_VINING_800_PRODUCT_ID 0x0119
|
||||
#define USB_USBCAN_PRO_5XCAN_PRODUCT_ID 0x011A
|
||||
#define USB_MINI_PCIE_1XCAN_PRODUCT_ID 0x011B
|
||||
|
||||
static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = {
|
||||
.quirks = KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP,
|
||||
@ -238,6 +241,12 @@ static const struct usb_device_id kvaser_usb_table[] = {
|
||||
.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
|
||||
{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_V3_PRODUCT_ID),
|
||||
.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
|
||||
{ USB_DEVICE(KVASER_VENDOR_ID, USB_VINING_800_PRODUCT_ID),
|
||||
.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
|
||||
{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5XCAN_PRODUCT_ID),
|
||||
.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
|
||||
{ USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_1XCAN_PRODUCT_ID),
|
||||
.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Copyright (C) 2017 - 2018 Sandvik Mining and Construction Oy
|
||||
*
|
||||
* Description:
|
||||
* This driver is developed for Axi CAN IP and for Zynq CANPS Controller.
|
||||
* This driver is developed for AXI CAN IP, AXI CANFD IP, CANPS and CANFD PS Controller.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
|
@ -2,7 +2,7 @@
|
||||
/*
|
||||
* linux/can/isotp.h
|
||||
*
|
||||
* Definitions for isotp CAN sockets (ISO 15765-2:2016)
|
||||
* Definitions for ISO 15765-2 CAN transport protocol sockets
|
||||
*
|
||||
* Copyright (c) 2020 Volkswagen Group Electronic Research
|
||||
* All rights reserved.
|
||||
|
@ -56,18 +56,17 @@ config CAN_GW
|
||||
source "net/can/j1939/Kconfig"
|
||||
|
||||
config CAN_ISOTP
|
||||
tristate "ISO 15765-2:2016 CAN transport protocol"
|
||||
tristate "ISO 15765-2 CAN transport protocol"
|
||||
help
|
||||
CAN Transport Protocols offer support for segmented Point-to-Point
|
||||
communication between CAN nodes via two defined CAN Identifiers.
|
||||
This protocol driver implements segmented data transfers for CAN CC
|
||||
(aka Classical CAN, CAN 2.0B) and CAN FD frame types which were
|
||||
introduced with ISO 15765-2:2016.
|
||||
As CAN frames can only transport a small amount of data bytes
|
||||
(max. 8 bytes for 'classic' CAN and max. 64 bytes for CAN FD) this
|
||||
(max. 8 bytes for CAN CC and max. 64 bytes for CAN FD) this
|
||||
segmentation is needed to transport longer Protocol Data Units (PDU)
|
||||
as needed e.g. for vehicle diagnosis (UDS, ISO 14229) or IP-over-CAN
|
||||
traffic.
|
||||
This protocol driver implements data transfers according to
|
||||
ISO 15765-2:2016 for 'classic' CAN and CAN FD frame types.
|
||||
If you want to perform automotive vehicle diagnostic services (UDS),
|
||||
say 'y'.
|
||||
|
||||
endif
|
||||
|
@ -72,7 +72,7 @@
|
||||
#include <net/sock.h>
|
||||
#include <net/net_namespace.h>
|
||||
|
||||
MODULE_DESCRIPTION("PF_CAN isotp 15765-2:2016 protocol");
|
||||
MODULE_DESCRIPTION("PF_CAN ISO 15765-2 transport protocol");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_AUTHOR("Oliver Hartkopp <socketcan@hartkopp.net>");
|
||||
MODULE_ALIAS("can-proto-6");
|
||||
@ -83,10 +83,11 @@ MODULE_ALIAS("can-proto-6");
|
||||
(CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \
|
||||
(CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))
|
||||
|
||||
/* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can
|
||||
* take full 32 bit values (4 Gbyte). We would need some good concept to handle
|
||||
* this between user space and kernel space. For now set the static buffer to
|
||||
* something about 8 kbyte to be able to test this new functionality.
|
||||
/* Since ISO 15765-2:2016 the CAN isotp protocol supports more than 4095
|
||||
* byte per ISO PDU as the FF_DL can take full 32 bit values (4 Gbyte).
|
||||
* We would need some good concept to handle this between user space and
|
||||
* kernel space. For now set the static buffer to something about 8 kbyte
|
||||
* to be able to test this new functionality.
|
||||
*/
|
||||
#define DEFAULT_MAX_PDU_SIZE 8300
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user