126ad340eSHenning Colliander // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
226ad340eSHenning Colliander /* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved.
326ad340eSHenning Colliander * Parts of this driver are based on the following:
4f33ad677SJimmy Assarsson * - Kvaser linux pciefd driver (version 5.42)
526ad340eSHenning Colliander * - PEAK linux canfd driver
626ad340eSHenning Colliander */
726ad340eSHenning Colliander
8954fb212SJimmy Assarsson #include <linux/bitfield.h>
91b83d0baSJimmy Assarsson #include <linux/can/dev.h>
101b83d0baSJimmy Assarsson #include <linux/device.h>
111b83d0baSJimmy Assarsson #include <linux/ethtool.h>
121b83d0baSJimmy Assarsson #include <linux/iopoll.h>
1326ad340eSHenning Colliander #include <linux/kernel.h>
14c496adafSJimmy Assarsson #include <linux/minmax.h>
1526ad340eSHenning Colliander #include <linux/module.h>
1626ad340eSHenning Colliander #include <linux/netdevice.h>
171b83d0baSJimmy Assarsson #include <linux/pci.h>
181b83d0baSJimmy Assarsson #include <linux/timer.h>
1926ad340eSHenning Colliander
2026ad340eSHenning Colliander MODULE_LICENSE("Dual BSD/GPL");
2126ad340eSHenning Colliander MODULE_AUTHOR("Kvaser AB <support@kvaser.com>");
2226ad340eSHenning Colliander MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
2326ad340eSHenning Colliander
2426ad340eSHenning Colliander #define KVASER_PCIEFD_DRV_NAME "kvaser_pciefd"
2526ad340eSHenning Colliander
2626ad340eSHenning Colliander #define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000)
2726ad340eSHenning Colliander #define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200))
282c470dbbSJimmy Assarsson #define KVASER_PCIEFD_MAX_ERR_REP 256U
292c470dbbSJimmy Assarsson #define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17U
30954fb212SJimmy Assarsson #define KVASER_PCIEFD_MAX_CAN_CHANNELS 4UL
312c470dbbSJimmy Assarsson #define KVASER_PCIEFD_DMA_COUNT 2U
3226ad340eSHenning Colliander
332c470dbbSJimmy Assarsson #define KVASER_PCIEFD_DMA_SIZE (4U * 1024U)
3426ad340eSHenning Colliander
3526ad340eSHenning Colliander #define KVASER_PCIEFD_VENDOR 0x1a07
36c2ad8129SJimmy Assarsson /* Altera based devices */
37488c07b4SJimmy Assarsson #define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d
38488c07b4SJimmy Assarsson #define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e
39488c07b4SJimmy Assarsson #define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f
40488c07b4SJimmy Assarsson #define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010
41488c07b4SJimmy Assarsson #define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011
4226ad340eSHenning Colliander
43f33ad677SJimmy Assarsson /* SmartFusion2 based devices */
44f33ad677SJimmy Assarsson #define KVASER_PCIEFD_2CAN_V3_DEVICE_ID 0x0012
45f33ad677SJimmy Assarsson #define KVASER_PCIEFD_1CAN_V3_DEVICE_ID 0x0013
46f33ad677SJimmy Assarsson #define KVASER_PCIEFD_4CAN_V2_DEVICE_ID 0x0014
47f33ad677SJimmy Assarsson #define KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID 0x0015
48f33ad677SJimmy Assarsson #define KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID 0x0016
49f33ad677SJimmy Assarsson
50c2ad8129SJimmy Assarsson /* Altera SerDes Enable 64-bit DMA address translation */
51c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_ALTERA_DMA_64BIT BIT(0)
52c2ad8129SJimmy Assarsson
53f33ad677SJimmy Assarsson /* SmartFusion2 SerDes LSB address translation mask */
54f33ad677SJimmy Assarsson #define KVASER_PCIEFD_SF2_DMA_LSB_MASK GENMASK(31, 12)
55f33ad677SJimmy Assarsson
5669335013SJimmy Assarsson /* Kvaser KCAN CAN controller registers */
5769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
5869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
5969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0
6069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_REG 0x400
6169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IEN_REG 0x408
6269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_REG 0x410
63f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG 0x414
6469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_REG 0x418
6569335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
6669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
6769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
6869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
6969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_REG 0x430
70c2ad8129SJimmy Assarsson /* System identification and information registers */
71c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_REG 0x8
72c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_CANFREQ_REG 0xc
73c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUSFREQ_REG 0x10
74c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUILD_REG 0x14
75c2ad8129SJimmy Assarsson /* Shared receive buffer FIFO registers */
76c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_FIFO_LAST_REG 0x1f4
77c2ad8129SJimmy Assarsson /* Shared receive buffer registers */
78c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_CMD_REG 0x0
79c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_IEN_REG 0x04
80c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_REG 0x0c
81c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_STAT_REG 0x10
82c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG 0x14
83c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_CTRL_REG 0x18
8469335013SJimmy Assarsson
8569335013SJimmy Assarsson /* System build information fields */
86954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24)
87954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK GENMASK(23, 16)
88954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK GENMASK(7, 0)
89954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK GENMASK(15, 1)
9026ad340eSHenning Colliander
9126ad340eSHenning Colliander /* Reset DMA buffer 0, 1 and FIFO offset */
9226ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5)
9369335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4)
9426ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CMD_FOR BIT(0)
9526ad340eSHenning Colliander
9626ad340eSHenning Colliander /* DMA underflow, buffer 0 and 1 */
9726ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13)
9869335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12)
9969335013SJimmy Assarsson /* DMA overflow, buffer 0 and 1 */
10069335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11)
10169335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10)
10269335013SJimmy Assarsson /* DMA packet done, buffer 0 and 1 */
10369335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9)
10469335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8)
10526ad340eSHenning Colliander
10669335013SJimmy Assarsson /* Got DMA support */
10769335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
10826ad340eSHenning Colliander /* DMA idle */
10926ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_STAT_DI BIT(15)
11026ad340eSHenning Colliander
111c589557dSJimmy Assarsson /* SRB current packet level */
112954fb212SJimmy Assarsson #define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK GENMASK(7, 0)
113c589557dSJimmy Assarsson
11426ad340eSHenning Colliander /* DMA Enable */
11526ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0)
11626ad340eSHenning Colliander
11769335013SJimmy Assarsson /* KCAN CTRL packet types */
118954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK GENMASK(31, 29)
119954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH 0x4
120954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFRAME 0x5
12126ad340eSHenning Colliander
12269335013SJimmy Assarsson /* Command sequence number */
123954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_SEQ_MASK GENMASK(23, 16)
124f4845741SJimmy Assarsson /* Command bits */
125f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_MASK GENMASK(5, 0)
12626ad340eSHenning Colliander /* Abort, flush and reset */
12726ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_CMD_AT BIT(1)
12869335013SJimmy Assarsson /* Request status packet */
12969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0)
13026ad340eSHenning Colliander
13126ad340eSHenning Colliander /* Transmitter unaligned */
13226ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17)
13369335013SJimmy Assarsson /* Tx FIFO empty */
13469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16)
13569335013SJimmy Assarsson /* Tx FIFO overflow */
13669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15)
13769335013SJimmy Assarsson /* Tx buffer flush done */
13869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14)
13969335013SJimmy Assarsson /* Abort done */
14069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13)
14169335013SJimmy Assarsson /* Rx FIFO overflow */
14269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5)
14369335013SJimmy Assarsson /* FDF bit when controller is in classic CAN mode */
14469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3)
14569335013SJimmy Assarsson /* Bus parameter protection error */
14669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2)
14769335013SJimmy Assarsson /* Tx FIFO unaligned end */
14869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1)
14969335013SJimmy Assarsson /* Tx FIFO unaligned read */
15069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0)
15126ad340eSHenning Colliander
15269335013SJimmy Assarsson /* Tx FIFO size */
153954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK GENMASK(23, 16)
154954fb212SJimmy Assarsson /* Tx FIFO current packet level */
155954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK GENMASK(7, 0)
15626ad340eSHenning Colliander
15769335013SJimmy Assarsson /* Current status packet sequence number */
158954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK GENMASK(31, 24)
15926ad340eSHenning Colliander /* Controller got CAN FD capability */
16026ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_STAT_FD BIT(19)
16169335013SJimmy Assarsson /* Controller got one-shot capability */
16269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16)
16369335013SJimmy Assarsson /* Controller in reset mode */
16469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15)
16569335013SJimmy Assarsson /* Reset mode request */
16669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14)
16769335013SJimmy Assarsson /* Bus off */
16869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11)
16969335013SJimmy Assarsson /* Idle state. Controller in reset mode and no abort or flush pending */
17069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10)
17169335013SJimmy Assarsson /* Abort request */
17269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_AR BIT(7)
17369335013SJimmy Assarsson /* Controller is bus off */
174f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK \
175f4845741SJimmy Assarsson (KVASER_PCIEFD_KCAN_STAT_AR | KVASER_PCIEFD_KCAN_STAT_BOFF | \
176f4845741SJimmy Assarsson KVASER_PCIEFD_KCAN_STAT_RMR | KVASER_PCIEFD_KCAN_STAT_IRM)
17726ad340eSHenning Colliander
17826ad340eSHenning Colliander /* Classic CAN mode */
17926ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31)
18069335013SJimmy Assarsson /* Active error flag enable. Clear to force error passive */
18169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23)
18269335013SJimmy Assarsson /* Acknowledgment packet type */
18369335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_APT BIT(20)
18469335013SJimmy Assarsson /* CAN FD non-ISO */
18569335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15)
18669335013SJimmy Assarsson /* Error packet enable */
18769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12)
18869335013SJimmy Assarsson /* Listen only mode */
18969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9)
19069335013SJimmy Assarsson /* Reset mode */
19169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_RM BIT(8)
19226ad340eSHenning Colliander
19369335013SJimmy Assarsson /* BTRN and BTRD fields */
194954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK GENMASK(30, 26)
195954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK GENMASK(25, 17)
196954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_SJW_MASK GENMASK(16, 13)
197954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_BRP_MASK GENMASK(12, 0)
19826ad340eSHenning Colliander
19969335013SJimmy Assarsson /* PWM Control fields */
200954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_TOP_MASK GENMASK(23, 16)
201954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK GENMASK(7, 0)
20226ad340eSHenning Colliander
20369335013SJimmy Assarsson /* KCAN packet type IDs */
204f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_DATA 0x0
205f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ACK 0x1
206f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_TXRQ 0x2
207f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ERROR 0x3
208f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 0x4
209f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 0x5
210f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 0x6
211f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_STATUS 0x8
212f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 0x9
21326ad340eSHenning Colliander
21469335013SJimmy Assarsson /* Common KCAN packet definitions, second word */
215954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_TYPE_MASK GENMASK(31, 28)
216954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_CHID_MASK GENMASK(27, 25)
217954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_SEQ_MASK GENMASK(7, 0)
21826ad340eSHenning Colliander
21969335013SJimmy Assarsson /* KCAN Transmit/Receive data packet, first word */
22026ad340eSHenning Colliander #define KVASER_PCIEFD_RPACKET_IDE BIT(30)
22126ad340eSHenning Colliander #define KVASER_PCIEFD_RPACKET_RTR BIT(29)
222954fb212SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_ID_MASK GENMASK(28, 0)
22369335013SJimmy Assarsson /* KCAN Transmit data packet, second word */
22426ad340eSHenning Colliander #define KVASER_PCIEFD_TPACKET_AREQ BIT(31)
22569335013SJimmy Assarsson #define KVASER_PCIEFD_TPACKET_SMS BIT(16)
22669335013SJimmy Assarsson /* KCAN Transmit/Receive data packet, second word */
22769335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_FDF BIT(15)
22869335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_BRS BIT(14)
22969335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_ESI BIT(13)
230954fb212SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_DLC_MASK GENMASK(11, 8)
23126ad340eSHenning Colliander
23269335013SJimmy Assarsson /* KCAN Transmit acknowledge packet, first word */
23326ad340eSHenning Colliander #define KVASER_PCIEFD_APACKET_NACK BIT(11)
23469335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_ABL BIT(10)
23569335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_CT BIT(9)
23669335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_FLU BIT(8)
23726ad340eSHenning Colliander
23869335013SJimmy Assarsson /* KCAN Status packet, first word */
23926ad340eSHenning Colliander #define KVASER_PCIEFD_SPACK_RMCD BIT(22)
24069335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_IRM BIT(21)
24169335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_IDET BIT(20)
24269335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_BOFF BIT(16)
243954fb212SJimmy Assarsson #define KVASER_PCIEFD_SPACK_RXERR_MASK GENMASK(15, 8)
244954fb212SJimmy Assarsson #define KVASER_PCIEFD_SPACK_TXERR_MASK GENMASK(7, 0)
24569335013SJimmy Assarsson /* KCAN Status packet, second word */
24626ad340eSHenning Colliander #define KVASER_PCIEFD_SPACK_EPLR BIT(24)
24769335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_EWLR BIT(23)
24869335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_AUTO BIT(21)
24926ad340eSHenning Colliander
25069335013SJimmy Assarsson /* KCAN Error detected packet, second word */
25136aea60fSJimmy Assarsson #define KVASER_PCIEFD_EPACK_DIR_TX BIT(0)
25236aea60fSJimmy Assarsson
253c2ad8129SJimmy Assarsson /* Macros for calculating addresses of registers */
254c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_GET_BLOCK_ADDR(pcie, block) \
255c2ad8129SJimmy Assarsson ((pcie)->reg_base + (pcie)->driver_data->address_offset->block)
256c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_PCI_IEN_ADDR(pcie) \
257c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_ien))
258c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_PCI_IRQ_ADDR(pcie) \
259c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_irq))
260c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SERDES_ADDR(pcie) \
261c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), serdes))
262c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_ADDR(pcie) \
263c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), sysid))
264c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_LOOPBACK_ADDR(pcie) \
265c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), loopback))
266c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) \
267c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb_fifo))
268c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_ADDR(pcie) \
269c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb))
270c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CH0_ADDR(pcie) \
271c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch0))
272c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CH1_ADDR(pcie) \
273c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch1))
274c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CHANNEL_SPAN(pcie) \
275c2ad8129SJimmy Assarsson (KVASER_PCIEFD_KCAN_CH1_ADDR((pcie)) - KVASER_PCIEFD_KCAN_CH0_ADDR((pcie)))
276c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i) \
277c2ad8129SJimmy Assarsson (KVASER_PCIEFD_KCAN_CH0_ADDR((pcie)) + (i) * KVASER_PCIEFD_KCAN_CHANNEL_SPAN((pcie)))
278c2ad8129SJimmy Assarsson
27926ad340eSHenning Colliander struct kvaser_pciefd;
280c2ad8129SJimmy Assarsson static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie,
281c2ad8129SJimmy Assarsson dma_addr_t addr, int index);
282f33ad677SJimmy Assarsson static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie,
283f33ad677SJimmy Assarsson dma_addr_t addr, int index);
284c2ad8129SJimmy Assarsson
285c2ad8129SJimmy Assarsson struct kvaser_pciefd_address_offset {
286c2ad8129SJimmy Assarsson u32 serdes;
287c2ad8129SJimmy Assarsson u32 pci_ien;
288c2ad8129SJimmy Assarsson u32 pci_irq;
289c2ad8129SJimmy Assarsson u32 sysid;
290c2ad8129SJimmy Assarsson u32 loopback;
291c2ad8129SJimmy Assarsson u32 kcan_srb_fifo;
292c2ad8129SJimmy Assarsson u32 kcan_srb;
293c2ad8129SJimmy Assarsson u32 kcan_ch0;
294c2ad8129SJimmy Assarsson u32 kcan_ch1;
295c2ad8129SJimmy Assarsson };
296c2ad8129SJimmy Assarsson
297c2ad8129SJimmy Assarsson struct kvaser_pciefd_dev_ops {
298c2ad8129SJimmy Assarsson void (*kvaser_pciefd_write_dma_map)(struct kvaser_pciefd *pcie,
299c2ad8129SJimmy Assarsson dma_addr_t addr, int index);
300c2ad8129SJimmy Assarsson };
301c2ad8129SJimmy Assarsson
302c2ad8129SJimmy Assarsson struct kvaser_pciefd_irq_mask {
303c2ad8129SJimmy Assarsson u32 kcan_rx0;
304c2ad8129SJimmy Assarsson u32 kcan_tx[KVASER_PCIEFD_MAX_CAN_CHANNELS];
305c2ad8129SJimmy Assarsson u32 all;
306c2ad8129SJimmy Assarsson };
307c2ad8129SJimmy Assarsson
308c2ad8129SJimmy Assarsson struct kvaser_pciefd_driver_data {
309c2ad8129SJimmy Assarsson const struct kvaser_pciefd_address_offset *address_offset;
310c2ad8129SJimmy Assarsson const struct kvaser_pciefd_irq_mask *irq_mask;
311c2ad8129SJimmy Assarsson const struct kvaser_pciefd_dev_ops *ops;
312c2ad8129SJimmy Assarsson };
313c2ad8129SJimmy Assarsson
314c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_address_offset kvaser_pciefd_altera_address_offset = {
315c2ad8129SJimmy Assarsson .serdes = 0x1000,
316c2ad8129SJimmy Assarsson .pci_ien = 0x50,
317c2ad8129SJimmy Assarsson .pci_irq = 0x40,
318c2ad8129SJimmy Assarsson .sysid = 0x1f020,
319c2ad8129SJimmy Assarsson .loopback = 0x1f000,
320c2ad8129SJimmy Assarsson .kcan_srb_fifo = 0x1f200,
321c2ad8129SJimmy Assarsson .kcan_srb = 0x1f400,
322c2ad8129SJimmy Assarsson .kcan_ch0 = 0x10000,
323c2ad8129SJimmy Assarsson .kcan_ch1 = 0x11000,
324c2ad8129SJimmy Assarsson };
325c2ad8129SJimmy Assarsson
326f33ad677SJimmy Assarsson static const struct kvaser_pciefd_address_offset kvaser_pciefd_sf2_address_offset = {
327f33ad677SJimmy Assarsson .serdes = 0x280c8,
328f33ad677SJimmy Assarsson .pci_ien = 0x102004,
329f33ad677SJimmy Assarsson .pci_irq = 0x102008,
330f33ad677SJimmy Assarsson .sysid = 0x100000,
331f33ad677SJimmy Assarsson .loopback = 0x103000,
332f33ad677SJimmy Assarsson .kcan_srb_fifo = 0x120000,
333f33ad677SJimmy Assarsson .kcan_srb = 0x121000,
334f33ad677SJimmy Assarsson .kcan_ch0 = 0x140000,
335f33ad677SJimmy Assarsson .kcan_ch1 = 0x142000,
336f33ad677SJimmy Assarsson };
337f33ad677SJimmy Assarsson
338c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_irq_mask kvaser_pciefd_altera_irq_mask = {
339c2ad8129SJimmy Assarsson .kcan_rx0 = BIT(4),
340c2ad8129SJimmy Assarsson .kcan_tx = { BIT(0), BIT(1), BIT(2), BIT(3) },
341c2ad8129SJimmy Assarsson .all = GENMASK(4, 0),
342c2ad8129SJimmy Assarsson };
343c2ad8129SJimmy Assarsson
344f33ad677SJimmy Assarsson static const struct kvaser_pciefd_irq_mask kvaser_pciefd_sf2_irq_mask = {
345f33ad677SJimmy Assarsson .kcan_rx0 = BIT(4),
346f33ad677SJimmy Assarsson .kcan_tx = { BIT(16), BIT(17), BIT(18), BIT(19) },
347f33ad677SJimmy Assarsson .all = GENMASK(19, 16) | BIT(4),
348f33ad677SJimmy Assarsson };
349f33ad677SJimmy Assarsson
350c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_dev_ops kvaser_pciefd_altera_dev_ops = {
351c2ad8129SJimmy Assarsson .kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_altera,
352c2ad8129SJimmy Assarsson };
353c2ad8129SJimmy Assarsson
354f33ad677SJimmy Assarsson static const struct kvaser_pciefd_dev_ops kvaser_pciefd_sf2_dev_ops = {
355f33ad677SJimmy Assarsson .kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_sf2,
356f33ad677SJimmy Assarsson };
357f33ad677SJimmy Assarsson
358c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_driver_data kvaser_pciefd_altera_driver_data = {
359c2ad8129SJimmy Assarsson .address_offset = &kvaser_pciefd_altera_address_offset,
360c2ad8129SJimmy Assarsson .irq_mask = &kvaser_pciefd_altera_irq_mask,
361c2ad8129SJimmy Assarsson .ops = &kvaser_pciefd_altera_dev_ops,
362c2ad8129SJimmy Assarsson };
36326ad340eSHenning Colliander
364f33ad677SJimmy Assarsson static const struct kvaser_pciefd_driver_data kvaser_pciefd_sf2_driver_data = {
365f33ad677SJimmy Assarsson .address_offset = &kvaser_pciefd_sf2_address_offset,
366f33ad677SJimmy Assarsson .irq_mask = &kvaser_pciefd_sf2_irq_mask,
367f33ad677SJimmy Assarsson .ops = &kvaser_pciefd_sf2_dev_ops,
368f33ad677SJimmy Assarsson };
369f33ad677SJimmy Assarsson
37026ad340eSHenning Colliander struct kvaser_pciefd_can {
37126ad340eSHenning Colliander struct can_priv can;
37226ad340eSHenning Colliander struct kvaser_pciefd *kv_pcie;
37326ad340eSHenning Colliander void __iomem *reg_base;
37426ad340eSHenning Colliander struct can_berr_counter bec;
37526ad340eSHenning Colliander u8 cmd_seq;
37626ad340eSHenning Colliander int err_rep_cnt;
37726ad340eSHenning Colliander int echo_idx;
37826ad340eSHenning Colliander spinlock_t lock; /* Locks sensitive registers (e.g. MODE) */
37926ad340eSHenning Colliander spinlock_t echo_lock; /* Locks the message echo buffer */
38026ad340eSHenning Colliander struct timer_list bec_poll_timer;
38126ad340eSHenning Colliander struct completion start_comp, flush_comp;
38226ad340eSHenning Colliander };
38326ad340eSHenning Colliander
38426ad340eSHenning Colliander struct kvaser_pciefd {
38526ad340eSHenning Colliander struct pci_dev *pci;
38626ad340eSHenning Colliander void __iomem *reg_base;
38726ad340eSHenning Colliander struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS];
388c2ad8129SJimmy Assarsson const struct kvaser_pciefd_driver_data *driver_data;
38926ad340eSHenning Colliander void *dma_data[KVASER_PCIEFD_DMA_COUNT];
39026ad340eSHenning Colliander u8 nr_channels;
391ec44dd57SChrister Beskow u32 bus_freq;
39226ad340eSHenning Colliander u32 freq;
39326ad340eSHenning Colliander u32 freq_to_ticks_div;
39426ad340eSHenning Colliander };
39526ad340eSHenning Colliander
39626ad340eSHenning Colliander struct kvaser_pciefd_rx_packet {
39726ad340eSHenning Colliander u32 header[2];
39826ad340eSHenning Colliander u64 timestamp;
39926ad340eSHenning Colliander };
40026ad340eSHenning Colliander
40126ad340eSHenning Colliander struct kvaser_pciefd_tx_packet {
40226ad340eSHenning Colliander u32 header[2];
40326ad340eSHenning Colliander u8 data[64];
40426ad340eSHenning Colliander };
40526ad340eSHenning Colliander
40626ad340eSHenning Colliander static const struct can_bittiming_const kvaser_pciefd_bittiming_const = {
40726ad340eSHenning Colliander .name = KVASER_PCIEFD_DRV_NAME,
40826ad340eSHenning Colliander .tseg1_min = 1,
409470e14c0SJimmy Assarsson .tseg1_max = 512,
41026ad340eSHenning Colliander .tseg2_min = 1,
41126ad340eSHenning Colliander .tseg2_max = 32,
41226ad340eSHenning Colliander .sjw_max = 16,
41326ad340eSHenning Colliander .brp_min = 1,
414470e14c0SJimmy Assarsson .brp_max = 8192,
41526ad340eSHenning Colliander .brp_inc = 1,
41626ad340eSHenning Colliander };
41726ad340eSHenning Colliander
41826ad340eSHenning Colliander static struct pci_device_id kvaser_pciefd_id_table[] = {
419488c07b4SJimmy Assarsson {
420488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID),
421c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
422488c07b4SJimmy Assarsson },
423488c07b4SJimmy Assarsson {
424488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID),
425c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
426488c07b4SJimmy Assarsson },
427488c07b4SJimmy Assarsson {
428488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID),
429c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
430488c07b4SJimmy Assarsson },
431488c07b4SJimmy Assarsson {
432488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID),
433c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
434488c07b4SJimmy Assarsson },
435488c07b4SJimmy Assarsson {
436488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID),
437c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
438488c07b4SJimmy Assarsson },
439488c07b4SJimmy Assarsson {
440f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2CAN_V3_DEVICE_ID),
441f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
442f33ad677SJimmy Assarsson },
443f33ad677SJimmy Assarsson {
444f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_1CAN_V3_DEVICE_ID),
445f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
446f33ad677SJimmy Assarsson },
447f33ad677SJimmy Assarsson {
448f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4CAN_V2_DEVICE_ID),
449f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
450f33ad677SJimmy Assarsson },
451f33ad677SJimmy Assarsson {
452f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID),
453f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
454f33ad677SJimmy Assarsson },
455f33ad677SJimmy Assarsson {
456f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID),
457f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
458f33ad677SJimmy Assarsson },
459f33ad677SJimmy Assarsson {
460488c07b4SJimmy Assarsson 0,
461488c07b4SJimmy Assarsson },
46226ad340eSHenning Colliander };
46326ad340eSHenning Colliander MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table);
46426ad340eSHenning Colliander
kvaser_pciefd_send_kcan_cmd(struct kvaser_pciefd_can * can,u32 cmd)465f4845741SJimmy Assarsson static inline void kvaser_pciefd_send_kcan_cmd(struct kvaser_pciefd_can *can, u32 cmd)
46626ad340eSHenning Colliander {
467f4845741SJimmy Assarsson iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_MASK, cmd) |
468f4845741SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_SEQ_MASK, ++can->cmd_seq),
469f4845741SJimmy Assarsson can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
470f4845741SJimmy Assarsson }
47126ad340eSHenning Colliander
kvaser_pciefd_request_status(struct kvaser_pciefd_can * can)472f4845741SJimmy Assarsson static inline void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can)
473f4845741SJimmy Assarsson {
474f4845741SJimmy Assarsson kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_SRQ);
475f4845741SJimmy Assarsson }
476f4845741SJimmy Assarsson
kvaser_pciefd_abort_flush_reset(struct kvaser_pciefd_can * can)477f4845741SJimmy Assarsson static inline void kvaser_pciefd_abort_flush_reset(struct kvaser_pciefd_can *can)
478f4845741SJimmy Assarsson {
479f4845741SJimmy Assarsson kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_AT);
48026ad340eSHenning Colliander }
48126ad340eSHenning Colliander
kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can * can)48226ad340eSHenning Colliander static void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can)
48326ad340eSHenning Colliander {
48426ad340eSHenning Colliander u32 mode;
48526ad340eSHenning Colliander unsigned long irq;
48626ad340eSHenning Colliander
48726ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq);
48826ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
48926ad340eSHenning Colliander if (!(mode & KVASER_PCIEFD_KCAN_MODE_EPEN)) {
49026ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
49126ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
49226ad340eSHenning Colliander }
49326ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq);
49426ad340eSHenning Colliander }
49526ad340eSHenning Colliander
kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can * can)49626ad340eSHenning Colliander static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can)
49726ad340eSHenning Colliander {
49826ad340eSHenning Colliander u32 mode;
49926ad340eSHenning Colliander unsigned long irq;
50026ad340eSHenning Colliander
50126ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq);
50226ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
50326ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_EPEN;
50426ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
50526ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq);
50626ad340eSHenning Colliander }
50726ad340eSHenning Colliander
kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can * can)50824aecf55SJimmy Assarsson static void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
50926ad340eSHenning Colliander {
51026ad340eSHenning Colliander u32 msk;
51126ad340eSHenning Colliander
51226ad340eSHenning Colliander msk = KVASER_PCIEFD_KCAN_IRQ_TE | KVASER_PCIEFD_KCAN_IRQ_ROF |
51326ad340eSHenning Colliander KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD |
51426ad340eSHenning Colliander KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL |
51526ad340eSHenning Colliander KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP |
516262d7a52SJimmy Assarsson KVASER_PCIEFD_KCAN_IRQ_TAR;
51726ad340eSHenning Colliander
51826ad340eSHenning Colliander iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
51926ad340eSHenning Colliander }
52026ad340eSHenning Colliander
kvaser_pciefd_set_skb_timestamp(const struct kvaser_pciefd * pcie,struct sk_buff * skb,u64 timestamp)5212d55e9f9SJimmy Assarsson static inline void kvaser_pciefd_set_skb_timestamp(const struct kvaser_pciefd *pcie,
5222d55e9f9SJimmy Assarsson struct sk_buff *skb, u64 timestamp)
5232d55e9f9SJimmy Assarsson {
5242d55e9f9SJimmy Assarsson skb_hwtstamps(skb)->hwtstamp =
5252d55e9f9SJimmy Assarsson ns_to_ktime(div_u64(timestamp * 1000, pcie->freq_to_ticks_div));
5262d55e9f9SJimmy Assarsson }
5272d55e9f9SJimmy Assarsson
kvaser_pciefd_setup_controller(struct kvaser_pciefd_can * can)52826ad340eSHenning Colliander static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
52926ad340eSHenning Colliander {
53026ad340eSHenning Colliander u32 mode;
53126ad340eSHenning Colliander unsigned long irq;
53226ad340eSHenning Colliander
53326ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq);
53426ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
53526ad340eSHenning Colliander if (can->can.ctrlmode & CAN_CTRLMODE_FD) {
53626ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM;
53726ad340eSHenning Colliander if (can->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)
53826ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_NIFDEN;
53926ad340eSHenning Colliander else
54026ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN;
54126ad340eSHenning Colliander } else {
54226ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_CCM;
54326ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN;
54426ad340eSHenning Colliander }
54526ad340eSHenning Colliander
54626ad340eSHenning Colliander if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
54726ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_LOM;
548bf7ac55eSJimmy Assarsson else
549bf7ac55eSJimmy Assarsson mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM;
55026ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_EEN;
55126ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
55226ad340eSHenning Colliander /* Use ACK packet type */
55326ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_APT;
55426ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_RM;
55526ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
55626ad340eSHenning Colliander
55726ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq);
55826ad340eSHenning Colliander }
55926ad340eSHenning Colliander
kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can * can)56026ad340eSHenning Colliander static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
56126ad340eSHenning Colliander {
56226ad340eSHenning Colliander u32 status;
56326ad340eSHenning Colliander unsigned long irq;
56426ad340eSHenning Colliander
56526ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq);
566f4845741SJimmy Assarsson iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
567262d7a52SJimmy Assarsson iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
56826ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
56926ad340eSHenning Colliander status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
57026ad340eSHenning Colliander if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
57126ad340eSHenning Colliander /* If controller is already idle, run abort, flush and reset */
572f4845741SJimmy Assarsson kvaser_pciefd_abort_flush_reset(can);
57326ad340eSHenning Colliander } else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) {
57426ad340eSHenning Colliander u32 mode;
57526ad340eSHenning Colliander
57626ad340eSHenning Colliander /* Put controller in reset mode */
57726ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
57826ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_RM;
57926ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
58026ad340eSHenning Colliander }
58126ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq);
58226ad340eSHenning Colliander }
58326ad340eSHenning Colliander
kvaser_pciefd_bus_on(struct kvaser_pciefd_can * can)58426ad340eSHenning Colliander static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
58526ad340eSHenning Colliander {
58626ad340eSHenning Colliander u32 mode;
58726ad340eSHenning Colliander unsigned long irq;
58826ad340eSHenning Colliander
58926ad340eSHenning Colliander del_timer(&can->bec_poll_timer);
59026ad340eSHenning Colliander if (!completion_done(&can->flush_comp))
59126ad340eSHenning Colliander kvaser_pciefd_start_controller_flush(can);
59226ad340eSHenning Colliander
59326ad340eSHenning Colliander if (!wait_for_completion_timeout(&can->flush_comp,
59426ad340eSHenning Colliander KVASER_PCIEFD_WAIT_TIMEOUT)) {
59526ad340eSHenning Colliander netdev_err(can->can.dev, "Timeout during bus on flush\n");
59626ad340eSHenning Colliander return -ETIMEDOUT;
59726ad340eSHenning Colliander }
59826ad340eSHenning Colliander
59926ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq);
60026ad340eSHenning Colliander iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
601f4845741SJimmy Assarsson iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
602262d7a52SJimmy Assarsson iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
60326ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
60426ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
60526ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_RM;
60626ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
60726ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq);
60826ad340eSHenning Colliander
60926ad340eSHenning Colliander if (!wait_for_completion_timeout(&can->start_comp,
61026ad340eSHenning Colliander KVASER_PCIEFD_WAIT_TIMEOUT)) {
61126ad340eSHenning Colliander netdev_err(can->can.dev, "Timeout during bus on reset\n");
61226ad340eSHenning Colliander return -ETIMEDOUT;
61326ad340eSHenning Colliander }
61426ad340eSHenning Colliander /* Reset interrupt handling */
61526ad340eSHenning Colliander iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
616f4845741SJimmy Assarsson iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
61726ad340eSHenning Colliander
61826ad340eSHenning Colliander kvaser_pciefd_set_tx_irq(can);
61926ad340eSHenning Colliander kvaser_pciefd_setup_controller(can);
62026ad340eSHenning Colliander can->can.state = CAN_STATE_ERROR_ACTIVE;
62126ad340eSHenning Colliander netif_wake_queue(can->can.dev);
62226ad340eSHenning Colliander can->bec.txerr = 0;
62326ad340eSHenning Colliander can->bec.rxerr = 0;
62426ad340eSHenning Colliander can->err_rep_cnt = 0;
62526ad340eSHenning Colliander
62626ad340eSHenning Colliander return 0;
62726ad340eSHenning Colliander }
62826ad340eSHenning Colliander
kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can * can)62926ad340eSHenning Colliander static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can)
63026ad340eSHenning Colliander {
6311910cd88SChrister Beskow u8 top;
63226ad340eSHenning Colliander u32 pwm_ctrl;
63326ad340eSHenning Colliander unsigned long irq;
63426ad340eSHenning Colliander
63526ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq);
63626ad340eSHenning Colliander pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
637954fb212SJimmy Assarsson top = FIELD_GET(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, pwm_ctrl);
6381910cd88SChrister Beskow /* Set duty cycle to zero */
639954fb212SJimmy Assarsson pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top);
64026ad340eSHenning Colliander iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
64126ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq);
64226ad340eSHenning Colliander }
64326ad340eSHenning Colliander
kvaser_pciefd_pwm_start(struct kvaser_pciefd_can * can)64426ad340eSHenning Colliander static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can)
64526ad340eSHenning Colliander {
64626ad340eSHenning Colliander int top, trigger;
64726ad340eSHenning Colliander u32 pwm_ctrl;
64826ad340eSHenning Colliander unsigned long irq;
64926ad340eSHenning Colliander
65026ad340eSHenning Colliander kvaser_pciefd_pwm_stop(can);
65126ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq);
65226ad340eSHenning Colliander /* Set frequency to 500 KHz */
653ec44dd57SChrister Beskow top = can->kv_pcie->bus_freq / (2 * 500000) - 1;
65426ad340eSHenning Colliander
655954fb212SJimmy Assarsson pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top);
656954fb212SJimmy Assarsson pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top);
65726ad340eSHenning Colliander iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
65826ad340eSHenning Colliander
65926ad340eSHenning Colliander /* Set duty cycle to 95 */
66026ad340eSHenning Colliander trigger = (100 * top - 95 * (top + 1) + 50) / 100;
661954fb212SJimmy Assarsson pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, trigger);
662954fb212SJimmy Assarsson pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top);
66326ad340eSHenning Colliander iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
66426ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq);
66526ad340eSHenning Colliander }
66626ad340eSHenning Colliander
kvaser_pciefd_open(struct net_device * netdev)66726ad340eSHenning Colliander static int kvaser_pciefd_open(struct net_device *netdev)
66826ad340eSHenning Colliander {
66926ad340eSHenning Colliander int err;
67026ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(netdev);
67126ad340eSHenning Colliander
67226ad340eSHenning Colliander err = open_candev(netdev);
67326ad340eSHenning Colliander if (err)
67426ad340eSHenning Colliander return err;
67526ad340eSHenning Colliander
67626ad340eSHenning Colliander err = kvaser_pciefd_bus_on(can);
67713a84cf3SZhang Qilong if (err) {
67813a84cf3SZhang Qilong close_candev(netdev);
67926ad340eSHenning Colliander return err;
68013a84cf3SZhang Qilong }
68126ad340eSHenning Colliander
68226ad340eSHenning Colliander return 0;
68326ad340eSHenning Colliander }
68426ad340eSHenning Colliander
kvaser_pciefd_stop(struct net_device * netdev)68526ad340eSHenning Colliander static int kvaser_pciefd_stop(struct net_device *netdev)
68626ad340eSHenning Colliander {
68726ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(netdev);
68826ad340eSHenning Colliander int ret = 0;
68926ad340eSHenning Colliander
69026ad340eSHenning Colliander /* Don't interrupt ongoing flush */
69126ad340eSHenning Colliander if (!completion_done(&can->flush_comp))
69226ad340eSHenning Colliander kvaser_pciefd_start_controller_flush(can);
69326ad340eSHenning Colliander
69426ad340eSHenning Colliander if (!wait_for_completion_timeout(&can->flush_comp,
69526ad340eSHenning Colliander KVASER_PCIEFD_WAIT_TIMEOUT)) {
69626ad340eSHenning Colliander netdev_err(can->can.dev, "Timeout during stop\n");
69726ad340eSHenning Colliander ret = -ETIMEDOUT;
69826ad340eSHenning Colliander } else {
69926ad340eSHenning Colliander iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
70026ad340eSHenning Colliander del_timer(&can->bec_poll_timer);
70126ad340eSHenning Colliander }
702aed0e6caSJimmy Assarsson can->can.state = CAN_STATE_STOPPED;
70326ad340eSHenning Colliander close_candev(netdev);
70426ad340eSHenning Colliander
70526ad340eSHenning Colliander return ret;
70626ad340eSHenning Colliander }
70726ad340eSHenning Colliander
kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet * p,struct kvaser_pciefd_can * can,struct sk_buff * skb)70826ad340eSHenning Colliander static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p,
70926ad340eSHenning Colliander struct kvaser_pciefd_can *can,
71026ad340eSHenning Colliander struct sk_buff *skb)
71126ad340eSHenning Colliander {
71226ad340eSHenning Colliander struct canfd_frame *cf = (struct canfd_frame *)skb->data;
71326ad340eSHenning Colliander int packet_size;
71426ad340eSHenning Colliander int seq = can->echo_idx;
71526ad340eSHenning Colliander
71626ad340eSHenning Colliander memset(p, 0, sizeof(*p));
71726ad340eSHenning Colliander if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
71826ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_TPACKET_SMS;
71926ad340eSHenning Colliander
72026ad340eSHenning Colliander if (cf->can_id & CAN_RTR_FLAG)
72126ad340eSHenning Colliander p->header[0] |= KVASER_PCIEFD_RPACKET_RTR;
72226ad340eSHenning Colliander
72326ad340eSHenning Colliander if (cf->can_id & CAN_EFF_FLAG)
72426ad340eSHenning Colliander p->header[0] |= KVASER_PCIEFD_RPACKET_IDE;
72526ad340eSHenning Colliander
726954fb212SJimmy Assarsson p->header[0] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_ID_MASK, cf->can_id);
72726ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ;
72826ad340eSHenning Colliander
72926ad340eSHenning Colliander if (can_is_canfd_skb(skb)) {
730f07008a2SJimmy Assarsson p->header[1] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK,
731f07008a2SJimmy Assarsson can_fd_len2dlc(cf->len));
73226ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_RPACKET_FDF;
73326ad340eSHenning Colliander if (cf->flags & CANFD_BRS)
73426ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_RPACKET_BRS;
73526ad340eSHenning Colliander if (cf->flags & CANFD_ESI)
73626ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_RPACKET_ESI;
737f07008a2SJimmy Assarsson } else {
738f07008a2SJimmy Assarsson p->header[1] |=
739f07008a2SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK,
740f07008a2SJimmy Assarsson can_get_cc_dlc((struct can_frame *)cf, can->can.ctrlmode));
74126ad340eSHenning Colliander }
74226ad340eSHenning Colliander
743954fb212SJimmy Assarsson p->header[1] |= FIELD_PREP(KVASER_PCIEFD_PACKET_SEQ_MASK, seq);
74426ad340eSHenning Colliander
74526ad340eSHenning Colliander packet_size = cf->len;
74626ad340eSHenning Colliander memcpy(p->data, cf->data, packet_size);
74726ad340eSHenning Colliander
74826ad340eSHenning Colliander return DIV_ROUND_UP(packet_size, 4);
74926ad340eSHenning Colliander }
75026ad340eSHenning Colliander
kvaser_pciefd_start_xmit(struct sk_buff * skb,struct net_device * netdev)75126ad340eSHenning Colliander static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
75226ad340eSHenning Colliander struct net_device *netdev)
75326ad340eSHenning Colliander {
75426ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(netdev);
75526ad340eSHenning Colliander unsigned long irq_flags;
75626ad340eSHenning Colliander struct kvaser_pciefd_tx_packet packet;
757f4845741SJimmy Assarsson int nr_words;
75826ad340eSHenning Colliander u8 count;
75926ad340eSHenning Colliander
760ae64438bSOliver Hartkopp if (can_dev_dropped_skb(netdev, skb))
76126ad340eSHenning Colliander return NETDEV_TX_OK;
76226ad340eSHenning Colliander
763f4845741SJimmy Assarsson nr_words = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
76426ad340eSHenning Colliander
76526ad340eSHenning Colliander spin_lock_irqsave(&can->echo_lock, irq_flags);
76626ad340eSHenning Colliander /* Prepare and save echo skb in internal slot */
7671dcb6e57SVincent Mailhol can_put_echo_skb(skb, netdev, can->echo_idx, 0);
76826ad340eSHenning Colliander
76926ad340eSHenning Colliander /* Move echo index to the next slot */
77026ad340eSHenning Colliander can->echo_idx = (can->echo_idx + 1) % can->can.echo_skb_max;
77126ad340eSHenning Colliander
77226ad340eSHenning Colliander /* Write header to fifo */
77326ad340eSHenning Colliander iowrite32(packet.header[0],
77426ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG);
77526ad340eSHenning Colliander iowrite32(packet.header[1],
77626ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG);
77726ad340eSHenning Colliander
778f4845741SJimmy Assarsson if (nr_words) {
779f4845741SJimmy Assarsson u32 data_last = ((u32 *)packet.data)[nr_words - 1];
78026ad340eSHenning Colliander
78126ad340eSHenning Colliander /* Write data to fifo, except last word */
78226ad340eSHenning Colliander iowrite32_rep(can->reg_base +
78326ad340eSHenning Colliander KVASER_PCIEFD_KCAN_FIFO_REG, packet.data,
784f4845741SJimmy Assarsson nr_words - 1);
78526ad340eSHenning Colliander /* Write last word to end of fifo */
78626ad340eSHenning Colliander __raw_writel(data_last, can->reg_base +
78726ad340eSHenning Colliander KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
78826ad340eSHenning Colliander } else {
78926ad340eSHenning Colliander /* Complete write to fifo */
79026ad340eSHenning Colliander __raw_writel(0, can->reg_base +
79126ad340eSHenning Colliander KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
79226ad340eSHenning Colliander }
79326ad340eSHenning Colliander
794954fb212SJimmy Assarsson count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
795f4845741SJimmy Assarsson ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
79626ad340eSHenning Colliander /* No room for a new message, stop the queue until at least one
79726ad340eSHenning Colliander * successful transmit
79826ad340eSHenning Colliander */
7996fdcd64eSJimmy Assarsson if (count >= can->can.echo_skb_max || can->can.echo_skb[can->echo_idx])
80026ad340eSHenning Colliander netif_stop_queue(netdev);
80126ad340eSHenning Colliander spin_unlock_irqrestore(&can->echo_lock, irq_flags);
80226ad340eSHenning Colliander
80326ad340eSHenning Colliander return NETDEV_TX_OK;
80426ad340eSHenning Colliander }
80526ad340eSHenning Colliander
kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can * can,bool data)80626ad340eSHenning Colliander static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
80726ad340eSHenning Colliander {
80826ad340eSHenning Colliander u32 mode, test, btrn;
80926ad340eSHenning Colliander unsigned long irq_flags;
81026ad340eSHenning Colliander int ret;
81126ad340eSHenning Colliander struct can_bittiming *bt;
81226ad340eSHenning Colliander
81326ad340eSHenning Colliander if (data)
81426ad340eSHenning Colliander bt = &can->can.data_bittiming;
81526ad340eSHenning Colliander else
81626ad340eSHenning Colliander bt = &can->can.bittiming;
81726ad340eSHenning Colliander
818954fb212SJimmy Assarsson btrn = FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK, bt->phase_seg2 - 1) |
819954fb212SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK, bt->prop_seg + bt->phase_seg1 - 1) |
820954fb212SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_SJW_MASK, bt->sjw - 1) |
821954fb212SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_BRP_MASK, bt->brp - 1);
82226ad340eSHenning Colliander
82326ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq_flags);
82426ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
82526ad340eSHenning Colliander /* Put the circuit in reset mode */
82626ad340eSHenning Colliander iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM,
82726ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
82826ad340eSHenning Colliander
82926ad340eSHenning Colliander /* Can only set bittiming if in reset mode */
83026ad340eSHenning Colliander ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG,
831f4845741SJimmy Assarsson test, test & KVASER_PCIEFD_KCAN_MODE_RM, 0, 10);
83226ad340eSHenning Colliander if (ret) {
83326ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq_flags);
83426ad340eSHenning Colliander return -EBUSY;
83526ad340eSHenning Colliander }
83626ad340eSHenning Colliander
83726ad340eSHenning Colliander if (data)
83826ad340eSHenning Colliander iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG);
83926ad340eSHenning Colliander else
84026ad340eSHenning Colliander iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG);
84126ad340eSHenning Colliander /* Restore previous reset mode status */
84226ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
84326ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq_flags);
844f4845741SJimmy Assarsson
84526ad340eSHenning Colliander return 0;
84626ad340eSHenning Colliander }
84726ad340eSHenning Colliander
kvaser_pciefd_set_nominal_bittiming(struct net_device * ndev)84826ad340eSHenning Colliander static int kvaser_pciefd_set_nominal_bittiming(struct net_device *ndev)
84926ad340eSHenning Colliander {
85026ad340eSHenning Colliander return kvaser_pciefd_set_bittiming(netdev_priv(ndev), false);
85126ad340eSHenning Colliander }
85226ad340eSHenning Colliander
kvaser_pciefd_set_data_bittiming(struct net_device * ndev)85326ad340eSHenning Colliander static int kvaser_pciefd_set_data_bittiming(struct net_device *ndev)
85426ad340eSHenning Colliander {
85526ad340eSHenning Colliander return kvaser_pciefd_set_bittiming(netdev_priv(ndev), true);
85626ad340eSHenning Colliander }
85726ad340eSHenning Colliander
kvaser_pciefd_set_mode(struct net_device * ndev,enum can_mode mode)85826ad340eSHenning Colliander static int kvaser_pciefd_set_mode(struct net_device *ndev, enum can_mode mode)
85926ad340eSHenning Colliander {
86026ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(ndev);
86126ad340eSHenning Colliander int ret = 0;
86226ad340eSHenning Colliander
86326ad340eSHenning Colliander switch (mode) {
86426ad340eSHenning Colliander case CAN_MODE_START:
86526ad340eSHenning Colliander if (!can->can.restart_ms)
86626ad340eSHenning Colliander ret = kvaser_pciefd_bus_on(can);
86726ad340eSHenning Colliander break;
86826ad340eSHenning Colliander default:
86926ad340eSHenning Colliander return -EOPNOTSUPP;
87026ad340eSHenning Colliander }
87126ad340eSHenning Colliander
87226ad340eSHenning Colliander return ret;
87326ad340eSHenning Colliander }
87426ad340eSHenning Colliander
kvaser_pciefd_get_berr_counter(const struct net_device * ndev,struct can_berr_counter * bec)87526ad340eSHenning Colliander static int kvaser_pciefd_get_berr_counter(const struct net_device *ndev,
87626ad340eSHenning Colliander struct can_berr_counter *bec)
87726ad340eSHenning Colliander {
87826ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(ndev);
87926ad340eSHenning Colliander
88026ad340eSHenning Colliander bec->rxerr = can->bec.rxerr;
88126ad340eSHenning Colliander bec->txerr = can->bec.txerr;
882f4845741SJimmy Assarsson
88326ad340eSHenning Colliander return 0;
88426ad340eSHenning Colliander }
88526ad340eSHenning Colliander
kvaser_pciefd_bec_poll_timer(struct timer_list * data)88626ad340eSHenning Colliander static void kvaser_pciefd_bec_poll_timer(struct timer_list *data)
88726ad340eSHenning Colliander {
88826ad340eSHenning Colliander struct kvaser_pciefd_can *can = from_timer(can, data, bec_poll_timer);
88926ad340eSHenning Colliander
89026ad340eSHenning Colliander kvaser_pciefd_enable_err_gen(can);
89126ad340eSHenning Colliander kvaser_pciefd_request_status(can);
89226ad340eSHenning Colliander can->err_rep_cnt = 0;
89326ad340eSHenning Colliander }
89426ad340eSHenning Colliander
89526ad340eSHenning Colliander static const struct net_device_ops kvaser_pciefd_netdev_ops = {
89626ad340eSHenning Colliander .ndo_open = kvaser_pciefd_open,
89726ad340eSHenning Colliander .ndo_stop = kvaser_pciefd_stop,
898fa5cc7e1SVincent Mailhol .ndo_eth_ioctl = can_eth_ioctl_hwts,
89926ad340eSHenning Colliander .ndo_start_xmit = kvaser_pciefd_start_xmit,
90026ad340eSHenning Colliander .ndo_change_mtu = can_change_mtu,
90126ad340eSHenning Colliander };
90226ad340eSHenning Colliander
903fa5cc7e1SVincent Mailhol static const struct ethtool_ops kvaser_pciefd_ethtool_ops = {
904fa5cc7e1SVincent Mailhol .get_ts_info = can_ethtool_op_get_ts_info_hwts,
905fa5cc7e1SVincent Mailhol };
906fa5cc7e1SVincent Mailhol
kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd * pcie)90726ad340eSHenning Colliander static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
90826ad340eSHenning Colliander {
90926ad340eSHenning Colliander int i;
91026ad340eSHenning Colliander
91126ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) {
91226ad340eSHenning Colliander struct net_device *netdev;
91326ad340eSHenning Colliander struct kvaser_pciefd_can *can;
914954fb212SJimmy Assarsson u32 status, tx_nr_packets_max;
91526ad340eSHenning Colliander
91626ad340eSHenning Colliander netdev = alloc_candev(sizeof(struct kvaser_pciefd_can),
91726ad340eSHenning Colliander KVASER_PCIEFD_CAN_TX_MAX_COUNT);
91826ad340eSHenning Colliander if (!netdev)
91926ad340eSHenning Colliander return -ENOMEM;
92026ad340eSHenning Colliander
92126ad340eSHenning Colliander can = netdev_priv(netdev);
92226ad340eSHenning Colliander netdev->netdev_ops = &kvaser_pciefd_netdev_ops;
923fa5cc7e1SVincent Mailhol netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops;
924c2ad8129SJimmy Assarsson can->reg_base = KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i);
92526ad340eSHenning Colliander can->kv_pcie = pcie;
92626ad340eSHenning Colliander can->cmd_seq = 0;
92726ad340eSHenning Colliander can->err_rep_cnt = 0;
92826ad340eSHenning Colliander can->bec.txerr = 0;
92926ad340eSHenning Colliander can->bec.rxerr = 0;
93026ad340eSHenning Colliander
93126ad340eSHenning Colliander init_completion(&can->start_comp);
93226ad340eSHenning Colliander init_completion(&can->flush_comp);
933f4845741SJimmy Assarsson timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 0);
93426ad340eSHenning Colliander
9357c6e6bceSJimmy Assarsson /* Disable Bus load reporting */
9367c6e6bceSJimmy Assarsson iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG);
9377c6e6bceSJimmy Assarsson
938954fb212SJimmy Assarsson tx_nr_packets_max =
939954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK,
940f4845741SJimmy Assarsson ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
94126ad340eSHenning Colliander
94226ad340eSHenning Colliander can->can.clock.freq = pcie->freq;
9436fdcd64eSJimmy Assarsson can->can.echo_skb_max = min(KVASER_PCIEFD_CAN_TX_MAX_COUNT, tx_nr_packets_max - 1);
94426ad340eSHenning Colliander can->echo_idx = 0;
94526ad340eSHenning Colliander spin_lock_init(&can->echo_lock);
94626ad340eSHenning Colliander spin_lock_init(&can->lock);
947f4845741SJimmy Assarsson
94826ad340eSHenning Colliander can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
94926ad340eSHenning Colliander can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const;
95026ad340eSHenning Colliander can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
951f4845741SJimmy Assarsson can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
95226ad340eSHenning Colliander can->can.do_set_mode = kvaser_pciefd_set_mode;
95326ad340eSHenning Colliander can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
95426ad340eSHenning Colliander can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
95526ad340eSHenning Colliander CAN_CTRLMODE_FD |
956f07008a2SJimmy Assarsson CAN_CTRLMODE_FD_NON_ISO |
957f07008a2SJimmy Assarsson CAN_CTRLMODE_CC_LEN8_DLC;
95826ad340eSHenning Colliander
95926ad340eSHenning Colliander status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
96026ad340eSHenning Colliander if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) {
96126ad340eSHenning Colliander dev_err(&pcie->pci->dev,
96226ad340eSHenning Colliander "CAN FD not supported as expected %d\n", i);
96326ad340eSHenning Colliander
96426ad340eSHenning Colliander free_candev(netdev);
96526ad340eSHenning Colliander return -ENODEV;
96626ad340eSHenning Colliander }
96726ad340eSHenning Colliander
96826ad340eSHenning Colliander if (status & KVASER_PCIEFD_KCAN_STAT_CAP)
96926ad340eSHenning Colliander can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
97026ad340eSHenning Colliander
97126ad340eSHenning Colliander netdev->flags |= IFF_ECHO;
97226ad340eSHenning Colliander SET_NETDEV_DEV(netdev, &pcie->pci->dev);
97326ad340eSHenning Colliander
974f4845741SJimmy Assarsson iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
975262d7a52SJimmy Assarsson iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
97626ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
97726ad340eSHenning Colliander
97826ad340eSHenning Colliander pcie->can[i] = can;
97926ad340eSHenning Colliander kvaser_pciefd_pwm_start(can);
98026ad340eSHenning Colliander }
98126ad340eSHenning Colliander
98226ad340eSHenning Colliander return 0;
98326ad340eSHenning Colliander }
98426ad340eSHenning Colliander
kvaser_pciefd_reg_candev(struct kvaser_pciefd * pcie)98526ad340eSHenning Colliander static int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie)
98626ad340eSHenning Colliander {
98726ad340eSHenning Colliander int i;
98826ad340eSHenning Colliander
98926ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) {
99026ad340eSHenning Colliander int err = register_candev(pcie->can[i]->can.dev);
99126ad340eSHenning Colliander
99226ad340eSHenning Colliander if (err) {
99326ad340eSHenning Colliander int j;
99426ad340eSHenning Colliander
99526ad340eSHenning Colliander /* Unregister all successfully registered devices. */
99626ad340eSHenning Colliander for (j = 0; j < i; j++)
99726ad340eSHenning Colliander unregister_candev(pcie->can[j]->can.dev);
99826ad340eSHenning Colliander return err;
99926ad340eSHenning Colliander }
100026ad340eSHenning Colliander }
100126ad340eSHenning Colliander
100226ad340eSHenning Colliander return 0;
100326ad340eSHenning Colliander }
100426ad340eSHenning Colliander
kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd * pcie,dma_addr_t addr,int index)1005c2ad8129SJimmy Assarsson static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie,
1006c2ad8129SJimmy Assarsson dma_addr_t addr, int index)
100726ad340eSHenning Colliander {
1008c2ad8129SJimmy Assarsson void __iomem *serdes_base;
100926ad340eSHenning Colliander u32 word1, word2;
101026ad340eSHenning Colliander
101126ad340eSHenning Colliander #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
1012c2ad8129SJimmy Assarsson word1 = addr | KVASER_PCIEFD_ALTERA_DMA_64BIT;
101326ad340eSHenning Colliander word2 = addr >> 32;
101426ad340eSHenning Colliander #else
101526ad340eSHenning Colliander word1 = addr;
101626ad340eSHenning Colliander word2 = 0;
101726ad340eSHenning Colliander #endif
1018c2ad8129SJimmy Assarsson serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x8 * index;
1019c2ad8129SJimmy Assarsson iowrite32(word1, serdes_base);
1020c2ad8129SJimmy Assarsson iowrite32(word2, serdes_base + 0x4);
102126ad340eSHenning Colliander }
102226ad340eSHenning Colliander
kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd * pcie,dma_addr_t addr,int index)1023f33ad677SJimmy Assarsson static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie,
1024f33ad677SJimmy Assarsson dma_addr_t addr, int index)
1025f33ad677SJimmy Assarsson {
1026f33ad677SJimmy Assarsson void __iomem *serdes_base;
1027f33ad677SJimmy Assarsson u32 lsb = addr & KVASER_PCIEFD_SF2_DMA_LSB_MASK;
1028f33ad677SJimmy Assarsson u32 msb = 0x0;
1029f33ad677SJimmy Assarsson
1030f33ad677SJimmy Assarsson #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
1031f33ad677SJimmy Assarsson msb = addr >> 32;
1032f33ad677SJimmy Assarsson #endif
1033f33ad677SJimmy Assarsson serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x10 * index;
1034f33ad677SJimmy Assarsson iowrite32(lsb, serdes_base);
1035f33ad677SJimmy Assarsson iowrite32(msb, serdes_base + 0x4);
1036f33ad677SJimmy Assarsson }
1037f33ad677SJimmy Assarsson
kvaser_pciefd_setup_dma(struct kvaser_pciefd * pcie)103826ad340eSHenning Colliander static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
103926ad340eSHenning Colliander {
104026ad340eSHenning Colliander int i;
104126ad340eSHenning Colliander u32 srb_status;
1042c589557dSJimmy Assarsson u32 srb_packet_count;
104326ad340eSHenning Colliander dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT];
104426ad340eSHenning Colliander
104526ad340eSHenning Colliander /* Disable the DMA */
1046c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
104726ad340eSHenning Colliander for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) {
1048f4845741SJimmy Assarsson pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev,
104926ad340eSHenning Colliander KVASER_PCIEFD_DMA_SIZE,
105026ad340eSHenning Colliander &dma_addr[i],
105126ad340eSHenning Colliander GFP_KERNEL);
105226ad340eSHenning Colliander
105326ad340eSHenning Colliander if (!pcie->dma_data[i] || !dma_addr[i]) {
105426ad340eSHenning Colliander dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n",
105526ad340eSHenning Colliander KVASER_PCIEFD_DMA_SIZE);
105626ad340eSHenning Colliander return -ENOMEM;
105726ad340eSHenning Colliander }
1058c2ad8129SJimmy Assarsson pcie->driver_data->ops->kvaser_pciefd_write_dma_map(pcie, dma_addr[i], i);
105926ad340eSHenning Colliander }
106026ad340eSHenning Colliander
106126ad340eSHenning Colliander /* Reset Rx FIFO, and both DMA buffers */
106226ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 |
106326ad340eSHenning Colliander KVASER_PCIEFD_SRB_CMD_RDB1,
1064c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
1065c589557dSJimmy Assarsson /* Empty Rx FIFO */
1066954fb212SJimmy Assarsson srb_packet_count =
1067954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK,
1068c2ad8129SJimmy Assarsson ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) +
1069c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG));
1070c589557dSJimmy Assarsson while (srb_packet_count) {
1071c589557dSJimmy Assarsson /* Drop current packet in FIFO */
1072c2ad8129SJimmy Assarsson ioread32(KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
1073c589557dSJimmy Assarsson srb_packet_count--;
1074c589557dSJimmy Assarsson }
1075c589557dSJimmy Assarsson
1076c2ad8129SJimmy Assarsson srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG);
107726ad340eSHenning Colliander if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) {
107826ad340eSHenning Colliander dev_err(&pcie->pci->dev, "DMA not idle before enabling\n");
107926ad340eSHenning Colliander return -EIO;
108026ad340eSHenning Colliander }
108126ad340eSHenning Colliander
108226ad340eSHenning Colliander /* Enable the DMA */
108326ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE,
1084c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
108526ad340eSHenning Colliander
108626ad340eSHenning Colliander return 0;
108726ad340eSHenning Colliander }
108826ad340eSHenning Colliander
kvaser_pciefd_setup_board(struct kvaser_pciefd * pcie)108926ad340eSHenning Colliander static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie)
109026ad340eSHenning Colliander {
1091954fb212SJimmy Assarsson u32 version, srb_status, build;
109226ad340eSHenning Colliander
1093c2ad8129SJimmy Assarsson version = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_VERSION_REG);
1094c496adafSJimmy Assarsson pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS,
1095954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version));
109626ad340eSHenning Colliander
1097c2ad8129SJimmy Assarsson build = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUILD_REG);
1098954fb212SJimmy Assarsson dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n",
1099954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version),
1100954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version),
1101954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build));
110226ad340eSHenning Colliander
1103c2ad8129SJimmy Assarsson srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG);
110426ad340eSHenning Colliander if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) {
1105f4845741SJimmy Assarsson dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n");
110626ad340eSHenning Colliander return -ENODEV;
110726ad340eSHenning Colliander }
110826ad340eSHenning Colliander
1109c2ad8129SJimmy Assarsson pcie->bus_freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUSFREQ_REG);
1110c2ad8129SJimmy Assarsson pcie->freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_CANFREQ_REG);
111126ad340eSHenning Colliander pcie->freq_to_ticks_div = pcie->freq / 1000000;
111226ad340eSHenning Colliander if (pcie->freq_to_ticks_div == 0)
111326ad340eSHenning Colliander pcie->freq_to_ticks_div = 1;
111426ad340eSHenning Colliander /* Turn off all loopback functionality */
1115c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_LOOPBACK_ADDR(pcie));
1116f4845741SJimmy Assarsson
1117c496adafSJimmy Assarsson return 0;
111826ad340eSHenning Colliander }
111926ad340eSHenning Colliander
kvaser_pciefd_handle_data_packet(struct kvaser_pciefd * pcie,struct kvaser_pciefd_rx_packet * p,__le32 * data)112026ad340eSHenning Colliander static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
112126ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p,
112226ad340eSHenning Colliander __le32 *data)
112326ad340eSHenning Colliander {
112426ad340eSHenning Colliander struct sk_buff *skb;
112526ad340eSHenning Colliander struct canfd_frame *cf;
112626ad340eSHenning Colliander struct can_priv *priv;
1127954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
1128f07008a2SJimmy Assarsson u8 dlc;
112926ad340eSHenning Colliander
113026ad340eSHenning Colliander if (ch_id >= pcie->nr_channels)
113126ad340eSHenning Colliander return -EIO;
113226ad340eSHenning Colliander
113326ad340eSHenning Colliander priv = &pcie->can[ch_id]->can;
1134f07008a2SJimmy Assarsson dlc = FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, p->header[1]);
113526ad340eSHenning Colliander
113626ad340eSHenning Colliander if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) {
113726ad340eSHenning Colliander skb = alloc_canfd_skb(priv->dev, &cf);
113826ad340eSHenning Colliander if (!skb) {
1139f4845741SJimmy Assarsson priv->dev->stats.rx_dropped++;
114026ad340eSHenning Colliander return -ENOMEM;
114126ad340eSHenning Colliander }
114226ad340eSHenning Colliander
1143f07008a2SJimmy Assarsson cf->len = can_fd_dlc2len(dlc);
114426ad340eSHenning Colliander if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS)
114526ad340eSHenning Colliander cf->flags |= CANFD_BRS;
114626ad340eSHenning Colliander if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI)
114726ad340eSHenning Colliander cf->flags |= CANFD_ESI;
114826ad340eSHenning Colliander } else {
114926ad340eSHenning Colliander skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf);
115026ad340eSHenning Colliander if (!skb) {
1151f4845741SJimmy Assarsson priv->dev->stats.rx_dropped++;
115226ad340eSHenning Colliander return -ENOMEM;
115326ad340eSHenning Colliander }
1154f07008a2SJimmy Assarsson can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->ctrlmode);
115526ad340eSHenning Colliander }
115626ad340eSHenning Colliander
1157954fb212SJimmy Assarsson cf->can_id = FIELD_GET(KVASER_PCIEFD_RPACKET_ID_MASK, p->header[0]);
115826ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE)
115926ad340eSHenning Colliander cf->can_id |= CAN_EFF_FLAG;
116026ad340eSHenning Colliander
11618e674ca7SVincent Mailhol if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) {
116226ad340eSHenning Colliander cf->can_id |= CAN_RTR_FLAG;
11638e674ca7SVincent Mailhol } else {
116426ad340eSHenning Colliander memcpy(cf->data, data, cf->len);
1165f4845741SJimmy Assarsson priv->dev->stats.rx_bytes += cf->len;
11668e674ca7SVincent Mailhol }
1167f4845741SJimmy Assarsson priv->dev->stats.rx_packets++;
11682d55e9f9SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp);
116926ad340eSHenning Colliander
117026ad340eSHenning Colliander return netif_rx(skb);
117126ad340eSHenning Colliander }
117226ad340eSHenning Colliander
kvaser_pciefd_change_state(struct kvaser_pciefd_can * can,struct can_frame * cf,enum can_state new_state,enum can_state tx_state,enum can_state rx_state)117326ad340eSHenning Colliander static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
117426ad340eSHenning Colliander struct can_frame *cf,
117526ad340eSHenning Colliander enum can_state new_state,
117626ad340eSHenning Colliander enum can_state tx_state,
117726ad340eSHenning Colliander enum can_state rx_state)
117826ad340eSHenning Colliander {
117926ad340eSHenning Colliander can_change_state(can->can.dev, cf, tx_state, rx_state);
118026ad340eSHenning Colliander
118126ad340eSHenning Colliander if (new_state == CAN_STATE_BUS_OFF) {
118226ad340eSHenning Colliander struct net_device *ndev = can->can.dev;
118326ad340eSHenning Colliander unsigned long irq_flags;
118426ad340eSHenning Colliander
118526ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq_flags);
118626ad340eSHenning Colliander netif_stop_queue(can->can.dev);
118726ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq_flags);
118826ad340eSHenning Colliander /* Prevent CAN controller from auto recover from bus off */
118926ad340eSHenning Colliander if (!can->can.restart_ms) {
119026ad340eSHenning Colliander kvaser_pciefd_start_controller_flush(can);
119126ad340eSHenning Colliander can_bus_off(ndev);
119226ad340eSHenning Colliander }
119326ad340eSHenning Colliander }
119426ad340eSHenning Colliander }
119526ad340eSHenning Colliander
kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet * p,struct can_berr_counter * bec,enum can_state * new_state,enum can_state * tx_state,enum can_state * rx_state)119626ad340eSHenning Colliander static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p,
119726ad340eSHenning Colliander struct can_berr_counter *bec,
119826ad340eSHenning Colliander enum can_state *new_state,
119926ad340eSHenning Colliander enum can_state *tx_state,
120026ad340eSHenning Colliander enum can_state *rx_state)
120126ad340eSHenning Colliander {
120226ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF ||
120326ad340eSHenning Colliander p->header[0] & KVASER_PCIEFD_SPACK_IRM)
120426ad340eSHenning Colliander *new_state = CAN_STATE_BUS_OFF;
120526ad340eSHenning Colliander else if (bec->txerr >= 255 || bec->rxerr >= 255)
120626ad340eSHenning Colliander *new_state = CAN_STATE_BUS_OFF;
120726ad340eSHenning Colliander else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR)
120826ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_PASSIVE;
120926ad340eSHenning Colliander else if (bec->txerr >= 128 || bec->rxerr >= 128)
121026ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_PASSIVE;
121126ad340eSHenning Colliander else if (p->header[1] & KVASER_PCIEFD_SPACK_EWLR)
121226ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_WARNING;
121326ad340eSHenning Colliander else if (bec->txerr >= 96 || bec->rxerr >= 96)
121426ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_WARNING;
121526ad340eSHenning Colliander else
121626ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_ACTIVE;
121726ad340eSHenning Colliander
121826ad340eSHenning Colliander *tx_state = bec->txerr >= bec->rxerr ? *new_state : 0;
121926ad340eSHenning Colliander *rx_state = bec->txerr <= bec->rxerr ? *new_state : 0;
122026ad340eSHenning Colliander }
122126ad340eSHenning Colliander
kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can * can,struct kvaser_pciefd_rx_packet * p)122226ad340eSHenning Colliander static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
122326ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p)
122426ad340eSHenning Colliander {
122526ad340eSHenning Colliander struct can_berr_counter bec;
122626ad340eSHenning Colliander enum can_state old_state, new_state, tx_state, rx_state;
122726ad340eSHenning Colliander struct net_device *ndev = can->can.dev;
122826ad340eSHenning Colliander struct sk_buff *skb;
122926ad340eSHenning Colliander struct can_frame *cf = NULL;
123026ad340eSHenning Colliander
123126ad340eSHenning Colliander old_state = can->can.state;
123226ad340eSHenning Colliander
1233954fb212SJimmy Assarsson bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]);
1234954fb212SJimmy Assarsson bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
123526ad340eSHenning Colliander
1236f4845741SJimmy Assarsson kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
123726ad340eSHenning Colliander skb = alloc_can_err_skb(ndev, &cf);
123826ad340eSHenning Colliander if (new_state != old_state) {
1239f4845741SJimmy Assarsson kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
124026ad340eSHenning Colliander if (old_state == CAN_STATE_BUS_OFF &&
124126ad340eSHenning Colliander new_state == CAN_STATE_ERROR_ACTIVE &&
124226ad340eSHenning Colliander can->can.restart_ms) {
124326ad340eSHenning Colliander can->can.can_stats.restarts++;
124426ad340eSHenning Colliander if (skb)
124526ad340eSHenning Colliander cf->can_id |= CAN_ERR_RESTARTED;
124626ad340eSHenning Colliander }
124726ad340eSHenning Colliander }
124826ad340eSHenning Colliander
124926ad340eSHenning Colliander can->err_rep_cnt++;
125026ad340eSHenning Colliander can->can.can_stats.bus_error++;
125136aea60fSJimmy Assarsson if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX)
1252f4845741SJimmy Assarsson ndev->stats.tx_errors++;
125336aea60fSJimmy Assarsson else
1254f4845741SJimmy Assarsson ndev->stats.rx_errors++;
125526ad340eSHenning Colliander
125626ad340eSHenning Colliander can->bec.txerr = bec.txerr;
125726ad340eSHenning Colliander can->bec.rxerr = bec.rxerr;
125826ad340eSHenning Colliander
125926ad340eSHenning Colliander if (!skb) {
1260f4845741SJimmy Assarsson ndev->stats.rx_dropped++;
126126ad340eSHenning Colliander return -ENOMEM;
126226ad340eSHenning Colliander }
126326ad340eSHenning Colliander
12642d55e9f9SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
12653e5c291cSVincent Mailhol cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT;
126626ad340eSHenning Colliander cf->data[6] = bec.txerr;
126726ad340eSHenning Colliander cf->data[7] = bec.rxerr;
126826ad340eSHenning Colliander
126926ad340eSHenning Colliander netif_rx(skb);
1270f4845741SJimmy Assarsson
127126ad340eSHenning Colliander return 0;
127226ad340eSHenning Colliander }
127326ad340eSHenning Colliander
kvaser_pciefd_handle_error_packet(struct kvaser_pciefd * pcie,struct kvaser_pciefd_rx_packet * p)127426ad340eSHenning Colliander static int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie,
127526ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p)
127626ad340eSHenning Colliander {
127726ad340eSHenning Colliander struct kvaser_pciefd_can *can;
1278954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
127926ad340eSHenning Colliander
128026ad340eSHenning Colliander if (ch_id >= pcie->nr_channels)
128126ad340eSHenning Colliander return -EIO;
128226ad340eSHenning Colliander
128326ad340eSHenning Colliander can = pcie->can[ch_id];
128426ad340eSHenning Colliander kvaser_pciefd_rx_error_frame(can, p);
128526ad340eSHenning Colliander if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP)
128626ad340eSHenning Colliander /* Do not report more errors, until bec_poll_timer expires */
128726ad340eSHenning Colliander kvaser_pciefd_disable_err_gen(can);
128826ad340eSHenning Colliander /* Start polling the error counters */
128926ad340eSHenning Colliander mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
1290f4845741SJimmy Assarsson
129126ad340eSHenning Colliander return 0;
129226ad340eSHenning Colliander }
129326ad340eSHenning Colliander
kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can * can,struct kvaser_pciefd_rx_packet * p)129426ad340eSHenning Colliander static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
129526ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p)
129626ad340eSHenning Colliander {
129726ad340eSHenning Colliander struct can_berr_counter bec;
129826ad340eSHenning Colliander enum can_state old_state, new_state, tx_state, rx_state;
129926ad340eSHenning Colliander
130026ad340eSHenning Colliander old_state = can->can.state;
130126ad340eSHenning Colliander
1302954fb212SJimmy Assarsson bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]);
1303954fb212SJimmy Assarsson bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
130426ad340eSHenning Colliander
1305f4845741SJimmy Assarsson kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
130626ad340eSHenning Colliander if (new_state != old_state) {
130726ad340eSHenning Colliander struct net_device *ndev = can->can.dev;
130826ad340eSHenning Colliander struct sk_buff *skb;
130926ad340eSHenning Colliander struct can_frame *cf;
131026ad340eSHenning Colliander
131126ad340eSHenning Colliander skb = alloc_can_err_skb(ndev, &cf);
131226ad340eSHenning Colliander if (!skb) {
1313f4845741SJimmy Assarsson ndev->stats.rx_dropped++;
131426ad340eSHenning Colliander return -ENOMEM;
131526ad340eSHenning Colliander }
131626ad340eSHenning Colliander
1317f4845741SJimmy Assarsson kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
131826ad340eSHenning Colliander if (old_state == CAN_STATE_BUS_OFF &&
131926ad340eSHenning Colliander new_state == CAN_STATE_ERROR_ACTIVE &&
132026ad340eSHenning Colliander can->can.restart_ms) {
132126ad340eSHenning Colliander can->can.can_stats.restarts++;
132226ad340eSHenning Colliander cf->can_id |= CAN_ERR_RESTARTED;
132326ad340eSHenning Colliander }
132426ad340eSHenning Colliander
13252d55e9f9SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
132626ad340eSHenning Colliander
132726ad340eSHenning Colliander cf->data[6] = bec.txerr;
132826ad340eSHenning Colliander cf->data[7] = bec.rxerr;
132926ad340eSHenning Colliander
133026ad340eSHenning Colliander netif_rx(skb);
133126ad340eSHenning Colliander }
133226ad340eSHenning Colliander can->bec.txerr = bec.txerr;
133326ad340eSHenning Colliander can->bec.rxerr = bec.rxerr;
133426ad340eSHenning Colliander /* Check if we need to poll the error counters */
133526ad340eSHenning Colliander if (bec.txerr || bec.rxerr)
133626ad340eSHenning Colliander mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
133726ad340eSHenning Colliander
133826ad340eSHenning Colliander return 0;
133926ad340eSHenning Colliander }
134026ad340eSHenning Colliander
kvaser_pciefd_handle_status_packet(struct kvaser_pciefd * pcie,struct kvaser_pciefd_rx_packet * p)134126ad340eSHenning Colliander static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
134226ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p)
134326ad340eSHenning Colliander {
134426ad340eSHenning Colliander struct kvaser_pciefd_can *can;
134526ad340eSHenning Colliander u8 cmdseq;
134626ad340eSHenning Colliander u32 status;
1347954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
134826ad340eSHenning Colliander
134926ad340eSHenning Colliander if (ch_id >= pcie->nr_channels)
135026ad340eSHenning Colliander return -EIO;
135126ad340eSHenning Colliander
135226ad340eSHenning Colliander can = pcie->can[ch_id];
135326ad340eSHenning Colliander
135426ad340eSHenning Colliander status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
1355954fb212SJimmy Assarsson cmdseq = FIELD_GET(KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK, status);
135626ad340eSHenning Colliander
135726ad340eSHenning Colliander /* Reset done, start abort and flush */
135826ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
135926ad340eSHenning Colliander p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
136026ad340eSHenning Colliander p->header[1] & KVASER_PCIEFD_SPACK_AUTO &&
1361954fb212SJimmy Assarsson cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) &&
136226ad340eSHenning Colliander status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
136326ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
136426ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
1365f4845741SJimmy Assarsson kvaser_pciefd_abort_flush_reset(can);
136626ad340eSHenning Colliander } else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
136726ad340eSHenning Colliander p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
1368954fb212SJimmy Assarsson cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) &&
136926ad340eSHenning Colliander status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
137026ad340eSHenning Colliander /* Reset detected, send end of flush if no packet are in FIFO */
1371f4845741SJimmy Assarsson u8 count;
137226ad340eSHenning Colliander
1373f4845741SJimmy Assarsson count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
1374f4845741SJimmy Assarsson ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
137526ad340eSHenning Colliander if (!count)
1376954fb212SJimmy Assarsson iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK,
1377954fb212SJimmy Assarsson KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH),
137826ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
137926ad340eSHenning Colliander } else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) &&
1380954fb212SJimmy Assarsson cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1])) {
138126ad340eSHenning Colliander /* Response to status request received */
138226ad340eSHenning Colliander kvaser_pciefd_handle_status_resp(can, p);
138326ad340eSHenning Colliander if (can->can.state != CAN_STATE_BUS_OFF &&
138426ad340eSHenning Colliander can->can.state != CAN_STATE_ERROR_ACTIVE) {
1385f4845741SJimmy Assarsson mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
138626ad340eSHenning Colliander }
138726ad340eSHenning Colliander } else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
1388f4845741SJimmy Assarsson !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK)) {
138926ad340eSHenning Colliander /* Reset to bus on detected */
139026ad340eSHenning Colliander if (!completion_done(&can->start_comp))
139126ad340eSHenning Colliander complete(&can->start_comp);
139226ad340eSHenning Colliander }
139326ad340eSHenning Colliander
139426ad340eSHenning Colliander return 0;
139526ad340eSHenning Colliander }
139626ad340eSHenning Colliander
kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can * can,struct kvaser_pciefd_rx_packet * p)139726ad340eSHenning Colliander static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can,
139826ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p)
139926ad340eSHenning Colliander {
140026ad340eSHenning Colliander struct sk_buff *skb;
140126ad340eSHenning Colliander struct can_frame *cf;
140226ad340eSHenning Colliander
140326ad340eSHenning Colliander skb = alloc_can_err_skb(can->can.dev, &cf);
1404f4845741SJimmy Assarsson can->can.dev->stats.tx_errors++;
140526ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) {
140626ad340eSHenning Colliander if (skb)
140726ad340eSHenning Colliander cf->can_id |= CAN_ERR_LOSTARB;
140826ad340eSHenning Colliander can->can.can_stats.arbitration_lost++;
140926ad340eSHenning Colliander } else if (skb) {
141026ad340eSHenning Colliander cf->can_id |= CAN_ERR_ACK;
141126ad340eSHenning Colliander }
141226ad340eSHenning Colliander
141326ad340eSHenning Colliander if (skb) {
141426ad340eSHenning Colliander cf->can_id |= CAN_ERR_BUSERROR;
1415ec681b91SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
141626ad340eSHenning Colliander netif_rx(skb);
141726ad340eSHenning Colliander } else {
1418f4845741SJimmy Assarsson can->can.dev->stats.rx_dropped++;
141926ad340eSHenning Colliander netdev_warn(can->can.dev, "No memory left for err_skb\n");
142026ad340eSHenning Colliander }
142126ad340eSHenning Colliander }
142226ad340eSHenning Colliander
kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd * pcie,struct kvaser_pciefd_rx_packet * p)142326ad340eSHenning Colliander static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie,
142426ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p)
142526ad340eSHenning Colliander {
142626ad340eSHenning Colliander struct kvaser_pciefd_can *can;
142726ad340eSHenning Colliander bool one_shot_fail = false;
1428954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
142926ad340eSHenning Colliander
143026ad340eSHenning Colliander if (ch_id >= pcie->nr_channels)
143126ad340eSHenning Colliander return -EIO;
143226ad340eSHenning Colliander
143326ad340eSHenning Colliander can = pcie->can[ch_id];
143426ad340eSHenning Colliander /* Ignore control packet ACK */
143526ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_APACKET_CT)
143626ad340eSHenning Colliander return 0;
143726ad340eSHenning Colliander
143826ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_APACKET_NACK) {
143926ad340eSHenning Colliander kvaser_pciefd_handle_nack_packet(can, p);
144026ad340eSHenning Colliander one_shot_fail = true;
144126ad340eSHenning Colliander }
144226ad340eSHenning Colliander
144326ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) {
144426ad340eSHenning Colliander netdev_dbg(can->can.dev, "Packet was flushed\n");
144526ad340eSHenning Colliander } else {
1446954fb212SJimmy Assarsson int echo_idx = FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[0]);
1447f4845741SJimmy Assarsson int len;
1448ec681b91SJimmy Assarsson u8 count;
1449ec681b91SJimmy Assarsson struct sk_buff *skb;
1450ec681b91SJimmy Assarsson
1451ec681b91SJimmy Assarsson skb = can->can.echo_skb[echo_idx];
1452ec681b91SJimmy Assarsson if (skb)
1453ec681b91SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp);
1454f4845741SJimmy Assarsson len = can_get_echo_skb(can->can.dev, echo_idx, NULL);
1455954fb212SJimmy Assarsson count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
1456f4845741SJimmy Assarsson ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
145726ad340eSHenning Colliander
14586fdcd64eSJimmy Assarsson if (count < can->can.echo_skb_max && netif_queue_stopped(can->can.dev))
145926ad340eSHenning Colliander netif_wake_queue(can->can.dev);
146026ad340eSHenning Colliander
146126ad340eSHenning Colliander if (!one_shot_fail) {
1462f4845741SJimmy Assarsson can->can.dev->stats.tx_bytes += len;
1463f4845741SJimmy Assarsson can->can.dev->stats.tx_packets++;
146426ad340eSHenning Colliander }
146526ad340eSHenning Colliander }
146626ad340eSHenning Colliander
146726ad340eSHenning Colliander return 0;
146826ad340eSHenning Colliander }
146926ad340eSHenning Colliander
kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd * pcie,struct kvaser_pciefd_rx_packet * p)147026ad340eSHenning Colliander static int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie,
147126ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p)
147226ad340eSHenning Colliander {
147326ad340eSHenning Colliander struct kvaser_pciefd_can *can;
1474954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
147526ad340eSHenning Colliander
147626ad340eSHenning Colliander if (ch_id >= pcie->nr_channels)
147726ad340eSHenning Colliander return -EIO;
147826ad340eSHenning Colliander
147926ad340eSHenning Colliander can = pcie->can[ch_id];
148026ad340eSHenning Colliander
148126ad340eSHenning Colliander if (!completion_done(&can->flush_comp))
148226ad340eSHenning Colliander complete(&can->flush_comp);
148326ad340eSHenning Colliander
148426ad340eSHenning Colliander return 0;
148526ad340eSHenning Colliander }
148626ad340eSHenning Colliander
kvaser_pciefd_read_packet(struct kvaser_pciefd * pcie,int * start_pos,int dma_buf)148726ad340eSHenning Colliander static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
148826ad340eSHenning Colliander int dma_buf)
148926ad340eSHenning Colliander {
149026ad340eSHenning Colliander __le32 *buffer = pcie->dma_data[dma_buf];
149126ad340eSHenning Colliander __le64 timestamp;
149226ad340eSHenning Colliander struct kvaser_pciefd_rx_packet packet;
149326ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p = &packet;
149426ad340eSHenning Colliander u8 type;
149526ad340eSHenning Colliander int pos = *start_pos;
149626ad340eSHenning Colliander int size;
149726ad340eSHenning Colliander int ret = 0;
149826ad340eSHenning Colliander
149926ad340eSHenning Colliander size = le32_to_cpu(buffer[pos++]);
150026ad340eSHenning Colliander if (!size) {
150126ad340eSHenning Colliander *start_pos = 0;
150226ad340eSHenning Colliander return 0;
150326ad340eSHenning Colliander }
150426ad340eSHenning Colliander
150526ad340eSHenning Colliander p->header[0] = le32_to_cpu(buffer[pos++]);
150626ad340eSHenning Colliander p->header[1] = le32_to_cpu(buffer[pos++]);
150726ad340eSHenning Colliander
150826ad340eSHenning Colliander /* Read 64-bit timestamp */
150926ad340eSHenning Colliander memcpy(×tamp, &buffer[pos], sizeof(__le64));
151026ad340eSHenning Colliander pos += 2;
151126ad340eSHenning Colliander p->timestamp = le64_to_cpu(timestamp);
151226ad340eSHenning Colliander
1513954fb212SJimmy Assarsson type = FIELD_GET(KVASER_PCIEFD_PACKET_TYPE_MASK, p->header[1]);
151426ad340eSHenning Colliander switch (type) {
151526ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_DATA:
151626ad340eSHenning Colliander ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]);
151726ad340eSHenning Colliander if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) {
151826ad340eSHenning Colliander u8 data_len;
151926ad340eSHenning Colliander
1520954fb212SJimmy Assarsson data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK,
1521954fb212SJimmy Assarsson p->header[1]));
152226ad340eSHenning Colliander pos += DIV_ROUND_UP(data_len, 4);
152326ad340eSHenning Colliander }
152426ad340eSHenning Colliander break;
152526ad340eSHenning Colliander
152626ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_ACK:
152726ad340eSHenning Colliander ret = kvaser_pciefd_handle_ack_packet(pcie, p);
152826ad340eSHenning Colliander break;
152926ad340eSHenning Colliander
153026ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_STATUS:
153126ad340eSHenning Colliander ret = kvaser_pciefd_handle_status_packet(pcie, p);
153226ad340eSHenning Colliander break;
153326ad340eSHenning Colliander
153426ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_ERROR:
153526ad340eSHenning Colliander ret = kvaser_pciefd_handle_error_packet(pcie, p);
153626ad340eSHenning Colliander break;
153726ad340eSHenning Colliander
153826ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK:
153926ad340eSHenning Colliander ret = kvaser_pciefd_handle_eflush_packet(pcie, p);
154026ad340eSHenning Colliander break;
154126ad340eSHenning Colliander
154226ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_ACK_DATA:
154326ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD:
154476c66ddfSJimmy Assarsson case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK:
154526ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_TXRQ:
154626ad340eSHenning Colliander dev_info(&pcie->pci->dev,
154726ad340eSHenning Colliander "Received unexpected packet type 0x%08X\n", type);
154826ad340eSHenning Colliander break;
154926ad340eSHenning Colliander
155026ad340eSHenning Colliander default:
155126ad340eSHenning Colliander dev_err(&pcie->pci->dev, "Unknown packet type 0x%08X\n", type);
155226ad340eSHenning Colliander ret = -EIO;
155326ad340eSHenning Colliander break;
155426ad340eSHenning Colliander }
155526ad340eSHenning Colliander
155626ad340eSHenning Colliander if (ret)
155726ad340eSHenning Colliander return ret;
155826ad340eSHenning Colliander
155926ad340eSHenning Colliander /* Position does not point to the end of the package,
156026ad340eSHenning Colliander * corrupted packet size?
156126ad340eSHenning Colliander */
156226ad340eSHenning Colliander if ((*start_pos + size) != pos)
156326ad340eSHenning Colliander return -EIO;
156426ad340eSHenning Colliander
156526ad340eSHenning Colliander /* Point to the next packet header, if any */
156626ad340eSHenning Colliander *start_pos = pos;
156726ad340eSHenning Colliander
156826ad340eSHenning Colliander return ret;
156926ad340eSHenning Colliander }
157026ad340eSHenning Colliander
kvaser_pciefd_read_buffer(struct kvaser_pciefd * pcie,int dma_buf)157126ad340eSHenning Colliander static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf)
157226ad340eSHenning Colliander {
157326ad340eSHenning Colliander int pos = 0;
157426ad340eSHenning Colliander int res = 0;
157526ad340eSHenning Colliander
157626ad340eSHenning Colliander do {
157726ad340eSHenning Colliander res = kvaser_pciefd_read_packet(pcie, &pos, dma_buf);
157826ad340eSHenning Colliander } while (!res && pos > 0 && pos < KVASER_PCIEFD_DMA_SIZE);
157926ad340eSHenning Colliander
158026ad340eSHenning Colliander return res;
158126ad340eSHenning Colliander }
158226ad340eSHenning Colliander
kvaser_pciefd_receive_irq(struct kvaser_pciefd * pcie)15836587b387SMartin Jocic static u32 kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
158426ad340eSHenning Colliander {
1585c2ad8129SJimmy Assarsson u32 irq = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
158626ad340eSHenning Colliander
15876587b387SMartin Jocic if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0)
158826ad340eSHenning Colliander kvaser_pciefd_read_buffer(pcie, 0);
158926ad340eSHenning Colliander
15906587b387SMartin Jocic if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1)
159126ad340eSHenning Colliander kvaser_pciefd_read_buffer(pcie, 1);
159226ad340eSHenning Colliander
159326ad340eSHenning Colliander if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 ||
159426ad340eSHenning Colliander irq & KVASER_PCIEFD_SRB_IRQ_DOF1 ||
159526ad340eSHenning Colliander irq & KVASER_PCIEFD_SRB_IRQ_DUF0 ||
159626ad340eSHenning Colliander irq & KVASER_PCIEFD_SRB_IRQ_DUF1)
159726ad340eSHenning Colliander dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq);
159826ad340eSHenning Colliander
1599c2ad8129SJimmy Assarsson iowrite32(irq, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
16006587b387SMartin Jocic return irq;
160126ad340eSHenning Colliander }
160226ad340eSHenning Colliander
kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can * can)160324aecf55SJimmy Assarsson static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
160426ad340eSHenning Colliander {
160526ad340eSHenning Colliander u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
160626ad340eSHenning Colliander
160726ad340eSHenning Colliander if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF)
160826ad340eSHenning Colliander netdev_err(can->can.dev, "Tx FIFO overflow\n");
160926ad340eSHenning Colliander
161026ad340eSHenning Colliander if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP)
161126ad340eSHenning Colliander netdev_err(can->can.dev,
161226ad340eSHenning Colliander "Fail to change bittiming, when not in reset mode\n");
161326ad340eSHenning Colliander
161426ad340eSHenning Colliander if (irq & KVASER_PCIEFD_KCAN_IRQ_FDIC)
161526ad340eSHenning Colliander netdev_err(can->can.dev, "CAN FD frame in CAN mode\n");
161626ad340eSHenning Colliander
161726ad340eSHenning Colliander if (irq & KVASER_PCIEFD_KCAN_IRQ_ROF)
161826ad340eSHenning Colliander netdev_err(can->can.dev, "Rx FIFO overflow\n");
161926ad340eSHenning Colliander
162026ad340eSHenning Colliander iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
162126ad340eSHenning Colliander }
162226ad340eSHenning Colliander
kvaser_pciefd_irq_handler(int irq,void * dev)162326ad340eSHenning Colliander static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
162426ad340eSHenning Colliander {
162526ad340eSHenning Colliander struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev;
1626c2ad8129SJimmy Assarsson const struct kvaser_pciefd_irq_mask *irq_mask = pcie->driver_data->irq_mask;
162700e4c694SMartin Jocic u32 pci_irq = ioread32(KVASER_PCIEFD_PCI_IRQ_ADDR(pcie));
16286587b387SMartin Jocic u32 srb_irq = 0;
1629*503901d3SMartin Jocic u32 srb_release = 0;
163026ad340eSHenning Colliander int i;
163126ad340eSHenning Colliander
163200e4c694SMartin Jocic if (!(pci_irq & irq_mask->all))
163326ad340eSHenning Colliander return IRQ_NONE;
163426ad340eSHenning Colliander
163500e4c694SMartin Jocic if (pci_irq & irq_mask->kcan_rx0)
16366587b387SMartin Jocic srb_irq = kvaser_pciefd_receive_irq(pcie);
163726ad340eSHenning Colliander
163826ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) {
163900e4c694SMartin Jocic if (pci_irq & irq_mask->kcan_tx[i])
164026ad340eSHenning Colliander kvaser_pciefd_transmit_irq(pcie->can[i]);
164126ad340eSHenning Colliander }
164226ad340eSHenning Colliander
1643*503901d3SMartin Jocic if (srb_irq & KVASER_PCIEFD_SRB_IRQ_DPD0)
1644*503901d3SMartin Jocic srb_release |= KVASER_PCIEFD_SRB_CMD_RDB0;
16456587b387SMartin Jocic
1646*503901d3SMartin Jocic if (srb_irq & KVASER_PCIEFD_SRB_IRQ_DPD1)
1647*503901d3SMartin Jocic srb_release |= KVASER_PCIEFD_SRB_CMD_RDB1;
1648*503901d3SMartin Jocic
1649*503901d3SMartin Jocic if (srb_release)
1650*503901d3SMartin Jocic iowrite32(srb_release, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
16516587b387SMartin Jocic
165226ad340eSHenning Colliander return IRQ_HANDLED;
165326ad340eSHenning Colliander }
165426ad340eSHenning Colliander
kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd * pcie)165526ad340eSHenning Colliander static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)
165626ad340eSHenning Colliander {
165726ad340eSHenning Colliander int i;
165826ad340eSHenning Colliander
165926ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) {
1660f4845741SJimmy Assarsson struct kvaser_pciefd_can *can = pcie->can[i];
1661f4845741SJimmy Assarsson
166226ad340eSHenning Colliander if (can) {
1663f4845741SJimmy Assarsson iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
166426ad340eSHenning Colliander kvaser_pciefd_pwm_stop(can);
166526ad340eSHenning Colliander free_candev(can->can.dev);
166626ad340eSHenning Colliander }
166726ad340eSHenning Colliander }
166826ad340eSHenning Colliander }
166926ad340eSHenning Colliander
kvaser_pciefd_probe(struct pci_dev * pdev,const struct pci_device_id * id)167026ad340eSHenning Colliander static int kvaser_pciefd_probe(struct pci_dev *pdev,
167126ad340eSHenning Colliander const struct pci_device_id *id)
167226ad340eSHenning Colliander {
167326ad340eSHenning Colliander int err;
167426ad340eSHenning Colliander struct kvaser_pciefd *pcie;
1675c2ad8129SJimmy Assarsson const struct kvaser_pciefd_irq_mask *irq_mask;
1676c2ad8129SJimmy Assarsson void __iomem *irq_en_base;
167726ad340eSHenning Colliander
167826ad340eSHenning Colliander pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
167926ad340eSHenning Colliander if (!pcie)
168026ad340eSHenning Colliander return -ENOMEM;
168126ad340eSHenning Colliander
168226ad340eSHenning Colliander pci_set_drvdata(pdev, pcie);
168326ad340eSHenning Colliander pcie->pci = pdev;
1684c2ad8129SJimmy Assarsson pcie->driver_data = (const struct kvaser_pciefd_driver_data *)id->driver_data;
1685c2ad8129SJimmy Assarsson irq_mask = pcie->driver_data->irq_mask;
168626ad340eSHenning Colliander
168726ad340eSHenning Colliander err = pci_enable_device(pdev);
168826ad340eSHenning Colliander if (err)
168926ad340eSHenning Colliander return err;
169026ad340eSHenning Colliander
169126ad340eSHenning Colliander err = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME);
169226ad340eSHenning Colliander if (err)
169326ad340eSHenning Colliander goto err_disable_pci;
169426ad340eSHenning Colliander
169526ad340eSHenning Colliander pcie->reg_base = pci_iomap(pdev, 0, 0);
169626ad340eSHenning Colliander if (!pcie->reg_base) {
169726ad340eSHenning Colliander err = -ENOMEM;
169826ad340eSHenning Colliander goto err_release_regions;
169926ad340eSHenning Colliander }
170026ad340eSHenning Colliander
170126ad340eSHenning Colliander err = kvaser_pciefd_setup_board(pcie);
170226ad340eSHenning Colliander if (err)
170326ad340eSHenning Colliander goto err_pci_iounmap;
170426ad340eSHenning Colliander
170526ad340eSHenning Colliander err = kvaser_pciefd_setup_dma(pcie);
170626ad340eSHenning Colliander if (err)
170726ad340eSHenning Colliander goto err_pci_iounmap;
170826ad340eSHenning Colliander
170926ad340eSHenning Colliander pci_set_master(pdev);
171026ad340eSHenning Colliander
171126ad340eSHenning Colliander err = kvaser_pciefd_setup_can_ctrls(pcie);
171226ad340eSHenning Colliander if (err)
171326ad340eSHenning Colliander goto err_teardown_can_ctrls;
171426ad340eSHenning Colliander
171584762d8dSJimmy Assarsson err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
171684762d8dSJimmy Assarsson IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
171784762d8dSJimmy Assarsson if (err)
171884762d8dSJimmy Assarsson goto err_teardown_can_ctrls;
171984762d8dSJimmy Assarsson
172026ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1,
1721c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
172226ad340eSHenning Colliander
172326ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 |
172426ad340eSHenning Colliander KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 |
172526ad340eSHenning Colliander KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1,
1726c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IEN_REG);
172726ad340eSHenning Colliander
17287c921556SJimmy Assarsson /* Enable PCI interrupts */
1729c2ad8129SJimmy Assarsson irq_en_base = KVASER_PCIEFD_PCI_IEN_ADDR(pcie);
1730c2ad8129SJimmy Assarsson iowrite32(irq_mask->all, irq_en_base);
173126ad340eSHenning Colliander /* Ready the DMA buffers */
173226ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
1733c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
173426ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
1735c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
173626ad340eSHenning Colliander
173726ad340eSHenning Colliander err = kvaser_pciefd_reg_candev(pcie);
173826ad340eSHenning Colliander if (err)
173926ad340eSHenning Colliander goto err_free_irq;
174026ad340eSHenning Colliander
174126ad340eSHenning Colliander return 0;
174226ad340eSHenning Colliander
174326ad340eSHenning Colliander err_free_irq:
174411164bc3SJimmy Assarsson /* Disable PCI interrupts */
1745c2ad8129SJimmy Assarsson iowrite32(0, irq_en_base);
174626ad340eSHenning Colliander free_irq(pcie->pci->irq, pcie);
174726ad340eSHenning Colliander
174826ad340eSHenning Colliander err_teardown_can_ctrls:
174926ad340eSHenning Colliander kvaser_pciefd_teardown_can_ctrls(pcie);
1750c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
175126ad340eSHenning Colliander pci_clear_master(pdev);
175226ad340eSHenning Colliander
175326ad340eSHenning Colliander err_pci_iounmap:
175426ad340eSHenning Colliander pci_iounmap(pdev, pcie->reg_base);
175526ad340eSHenning Colliander
175626ad340eSHenning Colliander err_release_regions:
175726ad340eSHenning Colliander pci_release_regions(pdev);
175826ad340eSHenning Colliander
175926ad340eSHenning Colliander err_disable_pci:
176026ad340eSHenning Colliander pci_disable_device(pdev);
176126ad340eSHenning Colliander
176226ad340eSHenning Colliander return err;
176326ad340eSHenning Colliander }
176426ad340eSHenning Colliander
kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd * pcie)176526ad340eSHenning Colliander static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie)
176626ad340eSHenning Colliander {
176726ad340eSHenning Colliander int i;
176826ad340eSHenning Colliander
176926ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) {
1770f4845741SJimmy Assarsson struct kvaser_pciefd_can *can = pcie->can[i];
1771f4845741SJimmy Assarsson
177226ad340eSHenning Colliander if (can) {
1773f4845741SJimmy Assarsson iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
177426ad340eSHenning Colliander unregister_candev(can->can.dev);
177526ad340eSHenning Colliander del_timer(&can->bec_poll_timer);
177626ad340eSHenning Colliander kvaser_pciefd_pwm_stop(can);
177726ad340eSHenning Colliander free_candev(can->can.dev);
177826ad340eSHenning Colliander }
177926ad340eSHenning Colliander }
178026ad340eSHenning Colliander }
178126ad340eSHenning Colliander
kvaser_pciefd_remove(struct pci_dev * pdev)178226ad340eSHenning Colliander static void kvaser_pciefd_remove(struct pci_dev *pdev)
178326ad340eSHenning Colliander {
178426ad340eSHenning Colliander struct kvaser_pciefd *pcie = pci_get_drvdata(pdev);
178526ad340eSHenning Colliander
178626ad340eSHenning Colliander kvaser_pciefd_remove_all_ctrls(pcie);
178726ad340eSHenning Colliander
17887c921556SJimmy Assarsson /* Disable interrupts */
1789c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
1790c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_PCI_IEN_ADDR(pcie));
179126ad340eSHenning Colliander
179226ad340eSHenning Colliander free_irq(pcie->pci->irq, pcie);
179326ad340eSHenning Colliander
179426ad340eSHenning Colliander pci_iounmap(pdev, pcie->reg_base);
179526ad340eSHenning Colliander pci_release_regions(pdev);
179626ad340eSHenning Colliander pci_disable_device(pdev);
179726ad340eSHenning Colliander }
179826ad340eSHenning Colliander
179926ad340eSHenning Colliander static struct pci_driver kvaser_pciefd = {
180026ad340eSHenning Colliander .name = KVASER_PCIEFD_DRV_NAME,
180126ad340eSHenning Colliander .id_table = kvaser_pciefd_id_table,
180226ad340eSHenning Colliander .probe = kvaser_pciefd_probe,
180326ad340eSHenning Colliander .remove = kvaser_pciefd_remove,
180426ad340eSHenning Colliander };
180526ad340eSHenning Colliander
180626ad340eSHenning Colliander module_pci_driver(kvaser_pciefd)
1807