xref: /openbmc/linux/drivers/net/can/kvaser_pciefd.c (revision c2ad812956aeb3068f4e24cacdbe9d0847de2bc5)
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:
426ad340eSHenning Colliander  *  - Kvaser linux pciefd driver (version 5.25)
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
36*c2ad8129SJimmy 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 
43*c2ad8129SJimmy Assarsson /* Altera SerDes Enable 64-bit DMA address translation */
44*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_ALTERA_DMA_64BIT BIT(0)
45*c2ad8129SJimmy Assarsson 
4669335013SJimmy Assarsson /* Kvaser KCAN CAN controller registers */
4769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
4869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
4969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0
5069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_REG 0x400
5169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IEN_REG 0x408
5269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_REG 0x410
53f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG 0x414
5469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_REG 0x418
5569335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
5669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
5769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
5869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
5969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_REG 0x430
60*c2ad8129SJimmy Assarsson /* System identification and information registers */
61*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_REG 0x8
62*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_CANFREQ_REG 0xc
63*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUSFREQ_REG 0x10
64*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUILD_REG 0x14
65*c2ad8129SJimmy Assarsson /* Shared receive buffer FIFO registers */
66*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_FIFO_LAST_REG 0x1f4
67*c2ad8129SJimmy Assarsson /* Shared receive buffer registers */
68*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_CMD_REG 0x0
69*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_IEN_REG 0x04
70*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_REG 0x0c
71*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_STAT_REG 0x10
72*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG 0x14
73*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_CTRL_REG 0x18
7469335013SJimmy Assarsson 
7569335013SJimmy Assarsson /* System build information fields */
76954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24)
77954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK GENMASK(23, 16)
78954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK GENMASK(7, 0)
79954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK GENMASK(15, 1)
8026ad340eSHenning Colliander 
8126ad340eSHenning Colliander /* Reset DMA buffer 0, 1 and FIFO offset */
8226ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5)
8369335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4)
8426ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CMD_FOR BIT(0)
8526ad340eSHenning Colliander 
8626ad340eSHenning Colliander /* DMA underflow, buffer 0 and 1 */
8726ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13)
8869335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12)
8969335013SJimmy Assarsson /* DMA overflow, buffer 0 and 1 */
9069335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11)
9169335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10)
9269335013SJimmy Assarsson /* DMA packet done, buffer 0 and 1 */
9369335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9)
9469335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8)
9526ad340eSHenning Colliander 
9669335013SJimmy Assarsson /* Got DMA support */
9769335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
9826ad340eSHenning Colliander /* DMA idle */
9926ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_STAT_DI BIT(15)
10026ad340eSHenning Colliander 
101c589557dSJimmy Assarsson /* SRB current packet level */
102954fb212SJimmy Assarsson #define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK GENMASK(7, 0)
103c589557dSJimmy Assarsson 
10426ad340eSHenning Colliander /* DMA Enable */
10526ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0)
10626ad340eSHenning Colliander 
10769335013SJimmy Assarsson /* KCAN CTRL packet types */
108954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK GENMASK(31, 29)
109954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH 0x4
110954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFRAME 0x5
11126ad340eSHenning Colliander 
11269335013SJimmy Assarsson /* Command sequence number */
113954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_SEQ_MASK GENMASK(23, 16)
114f4845741SJimmy Assarsson /* Command bits */
115f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_MASK GENMASK(5, 0)
11626ad340eSHenning Colliander /* Abort, flush and reset */
11726ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_CMD_AT BIT(1)
11869335013SJimmy Assarsson /* Request status packet */
11969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0)
12026ad340eSHenning Colliander 
12126ad340eSHenning Colliander /* Transmitter unaligned */
12226ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17)
12369335013SJimmy Assarsson /* Tx FIFO empty */
12469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16)
12569335013SJimmy Assarsson /* Tx FIFO overflow */
12669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15)
12769335013SJimmy Assarsson /* Tx buffer flush done */
12869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14)
12969335013SJimmy Assarsson /* Abort done */
13069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13)
13169335013SJimmy Assarsson /* Rx FIFO overflow */
13269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5)
13369335013SJimmy Assarsson /* FDF bit when controller is in classic CAN mode */
13469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3)
13569335013SJimmy Assarsson /* Bus parameter protection error */
13669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2)
13769335013SJimmy Assarsson /* Tx FIFO unaligned end */
13869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1)
13969335013SJimmy Assarsson /* Tx FIFO unaligned read */
14069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0)
14126ad340eSHenning Colliander 
14269335013SJimmy Assarsson /* Tx FIFO size */
143954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK GENMASK(23, 16)
144954fb212SJimmy Assarsson /* Tx FIFO current packet level */
145954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK GENMASK(7, 0)
14626ad340eSHenning Colliander 
14769335013SJimmy Assarsson /* Current status packet sequence number */
148954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK GENMASK(31, 24)
14926ad340eSHenning Colliander /* Controller got CAN FD capability */
15026ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_STAT_FD BIT(19)
15169335013SJimmy Assarsson /* Controller got one-shot capability */
15269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16)
15369335013SJimmy Assarsson /* Controller in reset mode */
15469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15)
15569335013SJimmy Assarsson /* Reset mode request */
15669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14)
15769335013SJimmy Assarsson /* Bus off */
15869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11)
15969335013SJimmy Assarsson /* Idle state. Controller in reset mode and no abort or flush pending */
16069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10)
16169335013SJimmy Assarsson /* Abort request */
16269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_AR BIT(7)
16369335013SJimmy Assarsson /* Controller is bus off */
164f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK \
165f4845741SJimmy Assarsson 	(KVASER_PCIEFD_KCAN_STAT_AR | KVASER_PCIEFD_KCAN_STAT_BOFF | \
166f4845741SJimmy Assarsson 	 KVASER_PCIEFD_KCAN_STAT_RMR | KVASER_PCIEFD_KCAN_STAT_IRM)
16726ad340eSHenning Colliander 
16826ad340eSHenning Colliander /* Classic CAN mode */
16926ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31)
17069335013SJimmy Assarsson /* Active error flag enable. Clear to force error passive */
17169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23)
17269335013SJimmy Assarsson /* Acknowledgment packet type */
17369335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_APT BIT(20)
17469335013SJimmy Assarsson /* CAN FD non-ISO */
17569335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15)
17669335013SJimmy Assarsson /* Error packet enable */
17769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12)
17869335013SJimmy Assarsson /* Listen only mode */
17969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9)
18069335013SJimmy Assarsson /* Reset mode */
18169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_RM BIT(8)
18226ad340eSHenning Colliander 
18369335013SJimmy Assarsson /* BTRN and BTRD fields */
184954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK GENMASK(30, 26)
185954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK GENMASK(25, 17)
186954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_SJW_MASK GENMASK(16, 13)
187954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_BRP_MASK GENMASK(12, 0)
18826ad340eSHenning Colliander 
18969335013SJimmy Assarsson /* PWM Control fields */
190954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_TOP_MASK GENMASK(23, 16)
191954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK GENMASK(7, 0)
19226ad340eSHenning Colliander 
19369335013SJimmy Assarsson /* KCAN packet type IDs */
194f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_DATA 0x0
195f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ACK 0x1
196f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_TXRQ 0x2
197f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ERROR 0x3
198f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 0x4
199f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 0x5
200f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 0x6
201f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_STATUS 0x8
202f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 0x9
20326ad340eSHenning Colliander 
20469335013SJimmy Assarsson /* Common KCAN packet definitions, second word */
205954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_TYPE_MASK GENMASK(31, 28)
206954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_CHID_MASK GENMASK(27, 25)
207954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_SEQ_MASK GENMASK(7, 0)
20826ad340eSHenning Colliander 
20969335013SJimmy Assarsson /* KCAN Transmit/Receive data packet, first word */
21026ad340eSHenning Colliander #define KVASER_PCIEFD_RPACKET_IDE BIT(30)
21126ad340eSHenning Colliander #define KVASER_PCIEFD_RPACKET_RTR BIT(29)
212954fb212SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_ID_MASK GENMASK(28, 0)
21369335013SJimmy Assarsson /* KCAN Transmit data packet, second word */
21426ad340eSHenning Colliander #define KVASER_PCIEFD_TPACKET_AREQ BIT(31)
21569335013SJimmy Assarsson #define KVASER_PCIEFD_TPACKET_SMS BIT(16)
21669335013SJimmy Assarsson /* KCAN Transmit/Receive data packet, second word */
21769335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_FDF BIT(15)
21869335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_BRS BIT(14)
21969335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_ESI BIT(13)
220954fb212SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_DLC_MASK GENMASK(11, 8)
22126ad340eSHenning Colliander 
22269335013SJimmy Assarsson /* KCAN Transmit acknowledge packet, first word */
22326ad340eSHenning Colliander #define KVASER_PCIEFD_APACKET_NACK BIT(11)
22469335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_ABL BIT(10)
22569335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_CT BIT(9)
22669335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_FLU BIT(8)
22726ad340eSHenning Colliander 
22869335013SJimmy Assarsson /* KCAN Status packet, first word */
22926ad340eSHenning Colliander #define KVASER_PCIEFD_SPACK_RMCD BIT(22)
23069335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_IRM BIT(21)
23169335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_IDET BIT(20)
23269335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_BOFF BIT(16)
233954fb212SJimmy Assarsson #define KVASER_PCIEFD_SPACK_RXERR_MASK GENMASK(15, 8)
234954fb212SJimmy Assarsson #define KVASER_PCIEFD_SPACK_TXERR_MASK GENMASK(7, 0)
23569335013SJimmy Assarsson /* KCAN Status packet, second word */
23626ad340eSHenning Colliander #define KVASER_PCIEFD_SPACK_EPLR BIT(24)
23769335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_EWLR BIT(23)
23869335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_AUTO BIT(21)
23926ad340eSHenning Colliander 
24069335013SJimmy Assarsson /* KCAN Error detected packet, second word */
24136aea60fSJimmy Assarsson #define KVASER_PCIEFD_EPACK_DIR_TX BIT(0)
24236aea60fSJimmy Assarsson 
243*c2ad8129SJimmy Assarsson /* Macros for calculating addresses of registers */
244*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_GET_BLOCK_ADDR(pcie, block) \
245*c2ad8129SJimmy Assarsson 	((pcie)->reg_base + (pcie)->driver_data->address_offset->block)
246*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_PCI_IEN_ADDR(pcie) \
247*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_ien))
248*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_PCI_IRQ_ADDR(pcie) \
249*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_irq))
250*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SERDES_ADDR(pcie) \
251*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), serdes))
252*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_ADDR(pcie) \
253*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), sysid))
254*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_LOOPBACK_ADDR(pcie) \
255*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), loopback))
256*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) \
257*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb_fifo))
258*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_ADDR(pcie) \
259*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb))
260*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CH0_ADDR(pcie) \
261*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch0))
262*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CH1_ADDR(pcie) \
263*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch1))
264*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CHANNEL_SPAN(pcie) \
265*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_KCAN_CH1_ADDR((pcie)) - KVASER_PCIEFD_KCAN_CH0_ADDR((pcie)))
266*c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i) \
267*c2ad8129SJimmy Assarsson 	(KVASER_PCIEFD_KCAN_CH0_ADDR((pcie)) + (i) * KVASER_PCIEFD_KCAN_CHANNEL_SPAN((pcie)))
268*c2ad8129SJimmy Assarsson 
26926ad340eSHenning Colliander struct kvaser_pciefd;
270*c2ad8129SJimmy Assarsson static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie,
271*c2ad8129SJimmy Assarsson 					       dma_addr_t addr, int index);
272*c2ad8129SJimmy Assarsson 
273*c2ad8129SJimmy Assarsson struct kvaser_pciefd_address_offset {
274*c2ad8129SJimmy Assarsson 	u32 serdes;
275*c2ad8129SJimmy Assarsson 	u32 pci_ien;
276*c2ad8129SJimmy Assarsson 	u32 pci_irq;
277*c2ad8129SJimmy Assarsson 	u32 sysid;
278*c2ad8129SJimmy Assarsson 	u32 loopback;
279*c2ad8129SJimmy Assarsson 	u32 kcan_srb_fifo;
280*c2ad8129SJimmy Assarsson 	u32 kcan_srb;
281*c2ad8129SJimmy Assarsson 	u32 kcan_ch0;
282*c2ad8129SJimmy Assarsson 	u32 kcan_ch1;
283*c2ad8129SJimmy Assarsson };
284*c2ad8129SJimmy Assarsson 
285*c2ad8129SJimmy Assarsson struct kvaser_pciefd_dev_ops {
286*c2ad8129SJimmy Assarsson 	void (*kvaser_pciefd_write_dma_map)(struct kvaser_pciefd *pcie,
287*c2ad8129SJimmy Assarsson 					    dma_addr_t addr, int index);
288*c2ad8129SJimmy Assarsson };
289*c2ad8129SJimmy Assarsson 
290*c2ad8129SJimmy Assarsson struct kvaser_pciefd_irq_mask {
291*c2ad8129SJimmy Assarsson 	u32 kcan_rx0;
292*c2ad8129SJimmy Assarsson 	u32 kcan_tx[KVASER_PCIEFD_MAX_CAN_CHANNELS];
293*c2ad8129SJimmy Assarsson 	u32 all;
294*c2ad8129SJimmy Assarsson };
295*c2ad8129SJimmy Assarsson 
296*c2ad8129SJimmy Assarsson struct kvaser_pciefd_driver_data {
297*c2ad8129SJimmy Assarsson 	const struct kvaser_pciefd_address_offset *address_offset;
298*c2ad8129SJimmy Assarsson 	const struct kvaser_pciefd_irq_mask *irq_mask;
299*c2ad8129SJimmy Assarsson 	const struct kvaser_pciefd_dev_ops *ops;
300*c2ad8129SJimmy Assarsson };
301*c2ad8129SJimmy Assarsson 
302*c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_address_offset kvaser_pciefd_altera_address_offset = {
303*c2ad8129SJimmy Assarsson 	.serdes = 0x1000,
304*c2ad8129SJimmy Assarsson 	.pci_ien = 0x50,
305*c2ad8129SJimmy Assarsson 	.pci_irq = 0x40,
306*c2ad8129SJimmy Assarsson 	.sysid = 0x1f020,
307*c2ad8129SJimmy Assarsson 	.loopback = 0x1f000,
308*c2ad8129SJimmy Assarsson 	.kcan_srb_fifo = 0x1f200,
309*c2ad8129SJimmy Assarsson 	.kcan_srb = 0x1f400,
310*c2ad8129SJimmy Assarsson 	.kcan_ch0 = 0x10000,
311*c2ad8129SJimmy Assarsson 	.kcan_ch1 = 0x11000,
312*c2ad8129SJimmy Assarsson };
313*c2ad8129SJimmy Assarsson 
314*c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_irq_mask kvaser_pciefd_altera_irq_mask = {
315*c2ad8129SJimmy Assarsson 	.kcan_rx0 = BIT(4),
316*c2ad8129SJimmy Assarsson 	.kcan_tx = { BIT(0), BIT(1), BIT(2), BIT(3) },
317*c2ad8129SJimmy Assarsson 	.all = GENMASK(4, 0),
318*c2ad8129SJimmy Assarsson };
319*c2ad8129SJimmy Assarsson 
320*c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_dev_ops kvaser_pciefd_altera_dev_ops = {
321*c2ad8129SJimmy Assarsson 	.kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_altera,
322*c2ad8129SJimmy Assarsson };
323*c2ad8129SJimmy Assarsson 
324*c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_driver_data kvaser_pciefd_altera_driver_data = {
325*c2ad8129SJimmy Assarsson 	.address_offset = &kvaser_pciefd_altera_address_offset,
326*c2ad8129SJimmy Assarsson 	.irq_mask = &kvaser_pciefd_altera_irq_mask,
327*c2ad8129SJimmy Assarsson 	.ops = &kvaser_pciefd_altera_dev_ops,
328*c2ad8129SJimmy Assarsson };
32926ad340eSHenning Colliander 
33026ad340eSHenning Colliander struct kvaser_pciefd_can {
33126ad340eSHenning Colliander 	struct can_priv can;
33226ad340eSHenning Colliander 	struct kvaser_pciefd *kv_pcie;
33326ad340eSHenning Colliander 	void __iomem *reg_base;
33426ad340eSHenning Colliander 	struct can_berr_counter bec;
33526ad340eSHenning Colliander 	u8 cmd_seq;
33626ad340eSHenning Colliander 	int err_rep_cnt;
33726ad340eSHenning Colliander 	int echo_idx;
33826ad340eSHenning Colliander 	spinlock_t lock; /* Locks sensitive registers (e.g. MODE) */
33926ad340eSHenning Colliander 	spinlock_t echo_lock; /* Locks the message echo buffer */
34026ad340eSHenning Colliander 	struct timer_list bec_poll_timer;
34126ad340eSHenning Colliander 	struct completion start_comp, flush_comp;
34226ad340eSHenning Colliander };
34326ad340eSHenning Colliander 
34426ad340eSHenning Colliander struct kvaser_pciefd {
34526ad340eSHenning Colliander 	struct pci_dev *pci;
34626ad340eSHenning Colliander 	void __iomem *reg_base;
34726ad340eSHenning Colliander 	struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS];
348*c2ad8129SJimmy Assarsson 	const struct kvaser_pciefd_driver_data *driver_data;
34926ad340eSHenning Colliander 	void *dma_data[KVASER_PCIEFD_DMA_COUNT];
35026ad340eSHenning Colliander 	u8 nr_channels;
351ec44dd57SChrister Beskow 	u32 bus_freq;
35226ad340eSHenning Colliander 	u32 freq;
35326ad340eSHenning Colliander 	u32 freq_to_ticks_div;
35426ad340eSHenning Colliander };
35526ad340eSHenning Colliander 
35626ad340eSHenning Colliander struct kvaser_pciefd_rx_packet {
35726ad340eSHenning Colliander 	u32 header[2];
35826ad340eSHenning Colliander 	u64 timestamp;
35926ad340eSHenning Colliander };
36026ad340eSHenning Colliander 
36126ad340eSHenning Colliander struct kvaser_pciefd_tx_packet {
36226ad340eSHenning Colliander 	u32 header[2];
36326ad340eSHenning Colliander 	u8 data[64];
36426ad340eSHenning Colliander };
36526ad340eSHenning Colliander 
36626ad340eSHenning Colliander static const struct can_bittiming_const kvaser_pciefd_bittiming_const = {
36726ad340eSHenning Colliander 	.name = KVASER_PCIEFD_DRV_NAME,
36826ad340eSHenning Colliander 	.tseg1_min = 1,
369470e14c0SJimmy Assarsson 	.tseg1_max = 512,
37026ad340eSHenning Colliander 	.tseg2_min = 1,
37126ad340eSHenning Colliander 	.tseg2_max = 32,
37226ad340eSHenning Colliander 	.sjw_max = 16,
37326ad340eSHenning Colliander 	.brp_min = 1,
374470e14c0SJimmy Assarsson 	.brp_max = 8192,
37526ad340eSHenning Colliander 	.brp_inc = 1,
37626ad340eSHenning Colliander };
37726ad340eSHenning Colliander 
37826ad340eSHenning Colliander static struct pci_device_id kvaser_pciefd_id_table[] = {
379488c07b4SJimmy Assarsson 	{
380488c07b4SJimmy Assarsson 		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID),
381*c2ad8129SJimmy Assarsson 		.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
382488c07b4SJimmy Assarsson 	},
383488c07b4SJimmy Assarsson 	{
384488c07b4SJimmy Assarsson 		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID),
385*c2ad8129SJimmy Assarsson 		.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
386488c07b4SJimmy Assarsson 	},
387488c07b4SJimmy Assarsson 	{
388488c07b4SJimmy Assarsson 		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID),
389*c2ad8129SJimmy Assarsson 		.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
390488c07b4SJimmy Assarsson 	},
391488c07b4SJimmy Assarsson 	{
392488c07b4SJimmy Assarsson 		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID),
393*c2ad8129SJimmy Assarsson 		.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
394488c07b4SJimmy Assarsson 	},
395488c07b4SJimmy Assarsson 	{
396488c07b4SJimmy Assarsson 		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID),
397*c2ad8129SJimmy Assarsson 		.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
398488c07b4SJimmy Assarsson 	},
399488c07b4SJimmy Assarsson 	{
400488c07b4SJimmy Assarsson 		0,
401488c07b4SJimmy Assarsson 	},
40226ad340eSHenning Colliander };
40326ad340eSHenning Colliander MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table);
40426ad340eSHenning Colliander 
405f4845741SJimmy Assarsson static inline void kvaser_pciefd_send_kcan_cmd(struct kvaser_pciefd_can *can, u32 cmd)
40626ad340eSHenning Colliander {
407f4845741SJimmy Assarsson 	iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_MASK, cmd) |
408f4845741SJimmy Assarsson 		  FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_SEQ_MASK, ++can->cmd_seq),
409f4845741SJimmy Assarsson 		  can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
410f4845741SJimmy Assarsson }
41126ad340eSHenning Colliander 
412f4845741SJimmy Assarsson static inline void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can)
413f4845741SJimmy Assarsson {
414f4845741SJimmy Assarsson 	kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_SRQ);
415f4845741SJimmy Assarsson }
416f4845741SJimmy Assarsson 
417f4845741SJimmy Assarsson static inline void kvaser_pciefd_abort_flush_reset(struct kvaser_pciefd_can *can)
418f4845741SJimmy Assarsson {
419f4845741SJimmy Assarsson 	kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_AT);
42026ad340eSHenning Colliander }
42126ad340eSHenning Colliander 
42226ad340eSHenning Colliander static void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can)
42326ad340eSHenning Colliander {
42426ad340eSHenning Colliander 	u32 mode;
42526ad340eSHenning Colliander 	unsigned long irq;
42626ad340eSHenning Colliander 
42726ad340eSHenning Colliander 	spin_lock_irqsave(&can->lock, irq);
42826ad340eSHenning Colliander 	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
42926ad340eSHenning Colliander 	if (!(mode & KVASER_PCIEFD_KCAN_MODE_EPEN)) {
43026ad340eSHenning Colliander 		mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
43126ad340eSHenning Colliander 		iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
43226ad340eSHenning Colliander 	}
43326ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->lock, irq);
43426ad340eSHenning Colliander }
43526ad340eSHenning Colliander 
43626ad340eSHenning Colliander static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can)
43726ad340eSHenning Colliander {
43826ad340eSHenning Colliander 	u32 mode;
43926ad340eSHenning Colliander 	unsigned long irq;
44026ad340eSHenning Colliander 
44126ad340eSHenning Colliander 	spin_lock_irqsave(&can->lock, irq);
44226ad340eSHenning Colliander 	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
44326ad340eSHenning Colliander 	mode &= ~KVASER_PCIEFD_KCAN_MODE_EPEN;
44426ad340eSHenning Colliander 	iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
44526ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->lock, irq);
44626ad340eSHenning Colliander }
44726ad340eSHenning Colliander 
44824aecf55SJimmy Assarsson static void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
44926ad340eSHenning Colliander {
45026ad340eSHenning Colliander 	u32 msk;
45126ad340eSHenning Colliander 
45226ad340eSHenning Colliander 	msk = KVASER_PCIEFD_KCAN_IRQ_TE | KVASER_PCIEFD_KCAN_IRQ_ROF |
45326ad340eSHenning Colliander 	      KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD |
45426ad340eSHenning Colliander 	      KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL |
45526ad340eSHenning Colliander 	      KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP |
456262d7a52SJimmy Assarsson 	      KVASER_PCIEFD_KCAN_IRQ_TAR;
45726ad340eSHenning Colliander 
45826ad340eSHenning Colliander 	iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
45926ad340eSHenning Colliander }
46026ad340eSHenning Colliander 
4612d55e9f9SJimmy Assarsson static inline void kvaser_pciefd_set_skb_timestamp(const struct kvaser_pciefd *pcie,
4622d55e9f9SJimmy Assarsson 						   struct sk_buff *skb, u64 timestamp)
4632d55e9f9SJimmy Assarsson {
4642d55e9f9SJimmy Assarsson 	skb_hwtstamps(skb)->hwtstamp =
4652d55e9f9SJimmy Assarsson 		ns_to_ktime(div_u64(timestamp * 1000, pcie->freq_to_ticks_div));
4662d55e9f9SJimmy Assarsson }
4672d55e9f9SJimmy Assarsson 
46826ad340eSHenning Colliander static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
46926ad340eSHenning Colliander {
47026ad340eSHenning Colliander 	u32 mode;
47126ad340eSHenning Colliander 	unsigned long irq;
47226ad340eSHenning Colliander 
47326ad340eSHenning Colliander 	spin_lock_irqsave(&can->lock, irq);
47426ad340eSHenning Colliander 	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
47526ad340eSHenning Colliander 	if (can->can.ctrlmode & CAN_CTRLMODE_FD) {
47626ad340eSHenning Colliander 		mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM;
47726ad340eSHenning Colliander 		if (can->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)
47826ad340eSHenning Colliander 			mode |= KVASER_PCIEFD_KCAN_MODE_NIFDEN;
47926ad340eSHenning Colliander 		else
48026ad340eSHenning Colliander 			mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN;
48126ad340eSHenning Colliander 	} else {
48226ad340eSHenning Colliander 		mode |= KVASER_PCIEFD_KCAN_MODE_CCM;
48326ad340eSHenning Colliander 		mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN;
48426ad340eSHenning Colliander 	}
48526ad340eSHenning Colliander 
48626ad340eSHenning Colliander 	if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
48726ad340eSHenning Colliander 		mode |= KVASER_PCIEFD_KCAN_MODE_LOM;
488bf7ac55eSJimmy Assarsson 	else
489bf7ac55eSJimmy Assarsson 		mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM;
49026ad340eSHenning Colliander 	mode |= KVASER_PCIEFD_KCAN_MODE_EEN;
49126ad340eSHenning Colliander 	mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
49226ad340eSHenning Colliander 	/* Use ACK packet type */
49326ad340eSHenning Colliander 	mode &= ~KVASER_PCIEFD_KCAN_MODE_APT;
49426ad340eSHenning Colliander 	mode &= ~KVASER_PCIEFD_KCAN_MODE_RM;
49526ad340eSHenning Colliander 	iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
49626ad340eSHenning Colliander 
49726ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->lock, irq);
49826ad340eSHenning Colliander }
49926ad340eSHenning Colliander 
50026ad340eSHenning Colliander static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
50126ad340eSHenning Colliander {
50226ad340eSHenning Colliander 	u32 status;
50326ad340eSHenning Colliander 	unsigned long irq;
50426ad340eSHenning Colliander 
50526ad340eSHenning Colliander 	spin_lock_irqsave(&can->lock, irq);
506f4845741SJimmy Assarsson 	iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
507262d7a52SJimmy Assarsson 	iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
50826ad340eSHenning Colliander 		  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
50926ad340eSHenning Colliander 	status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
51026ad340eSHenning Colliander 	if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
51126ad340eSHenning Colliander 		/* If controller is already idle, run abort, flush and reset */
512f4845741SJimmy Assarsson 		kvaser_pciefd_abort_flush_reset(can);
51326ad340eSHenning Colliander 	} else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) {
51426ad340eSHenning Colliander 		u32 mode;
51526ad340eSHenning Colliander 
51626ad340eSHenning Colliander 		/* Put controller in reset mode */
51726ad340eSHenning Colliander 		mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
51826ad340eSHenning Colliander 		mode |= KVASER_PCIEFD_KCAN_MODE_RM;
51926ad340eSHenning Colliander 		iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
52026ad340eSHenning Colliander 	}
52126ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->lock, irq);
52226ad340eSHenning Colliander }
52326ad340eSHenning Colliander 
52426ad340eSHenning Colliander static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
52526ad340eSHenning Colliander {
52626ad340eSHenning Colliander 	u32 mode;
52726ad340eSHenning Colliander 	unsigned long irq;
52826ad340eSHenning Colliander 
52926ad340eSHenning Colliander 	del_timer(&can->bec_poll_timer);
53026ad340eSHenning Colliander 	if (!completion_done(&can->flush_comp))
53126ad340eSHenning Colliander 		kvaser_pciefd_start_controller_flush(can);
53226ad340eSHenning Colliander 
53326ad340eSHenning Colliander 	if (!wait_for_completion_timeout(&can->flush_comp,
53426ad340eSHenning Colliander 					 KVASER_PCIEFD_WAIT_TIMEOUT)) {
53526ad340eSHenning Colliander 		netdev_err(can->can.dev, "Timeout during bus on flush\n");
53626ad340eSHenning Colliander 		return -ETIMEDOUT;
53726ad340eSHenning Colliander 	}
53826ad340eSHenning Colliander 
53926ad340eSHenning Colliander 	spin_lock_irqsave(&can->lock, irq);
54026ad340eSHenning Colliander 	iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
541f4845741SJimmy Assarsson 	iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
542262d7a52SJimmy Assarsson 	iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
54326ad340eSHenning Colliander 		  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
54426ad340eSHenning Colliander 	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
54526ad340eSHenning Colliander 	mode &= ~KVASER_PCIEFD_KCAN_MODE_RM;
54626ad340eSHenning Colliander 	iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
54726ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->lock, irq);
54826ad340eSHenning Colliander 
54926ad340eSHenning Colliander 	if (!wait_for_completion_timeout(&can->start_comp,
55026ad340eSHenning Colliander 					 KVASER_PCIEFD_WAIT_TIMEOUT)) {
55126ad340eSHenning Colliander 		netdev_err(can->can.dev, "Timeout during bus on reset\n");
55226ad340eSHenning Colliander 		return -ETIMEDOUT;
55326ad340eSHenning Colliander 	}
55426ad340eSHenning Colliander 	/* Reset interrupt handling */
55526ad340eSHenning Colliander 	iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
556f4845741SJimmy Assarsson 	iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
55726ad340eSHenning Colliander 
55826ad340eSHenning Colliander 	kvaser_pciefd_set_tx_irq(can);
55926ad340eSHenning Colliander 	kvaser_pciefd_setup_controller(can);
56026ad340eSHenning Colliander 	can->can.state = CAN_STATE_ERROR_ACTIVE;
56126ad340eSHenning Colliander 	netif_wake_queue(can->can.dev);
56226ad340eSHenning Colliander 	can->bec.txerr = 0;
56326ad340eSHenning Colliander 	can->bec.rxerr = 0;
56426ad340eSHenning Colliander 	can->err_rep_cnt = 0;
56526ad340eSHenning Colliander 
56626ad340eSHenning Colliander 	return 0;
56726ad340eSHenning Colliander }
56826ad340eSHenning Colliander 
56926ad340eSHenning Colliander static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can)
57026ad340eSHenning Colliander {
5711910cd88SChrister Beskow 	u8 top;
57226ad340eSHenning Colliander 	u32 pwm_ctrl;
57326ad340eSHenning Colliander 	unsigned long irq;
57426ad340eSHenning Colliander 
57526ad340eSHenning Colliander 	spin_lock_irqsave(&can->lock, irq);
57626ad340eSHenning Colliander 	pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
577954fb212SJimmy Assarsson 	top = FIELD_GET(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, pwm_ctrl);
5781910cd88SChrister Beskow 	/* Set duty cycle to zero */
579954fb212SJimmy Assarsson 	pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top);
58026ad340eSHenning Colliander 	iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
58126ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->lock, irq);
58226ad340eSHenning Colliander }
58326ad340eSHenning Colliander 
58426ad340eSHenning Colliander static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can)
58526ad340eSHenning Colliander {
58626ad340eSHenning Colliander 	int top, trigger;
58726ad340eSHenning Colliander 	u32 pwm_ctrl;
58826ad340eSHenning Colliander 	unsigned long irq;
58926ad340eSHenning Colliander 
59026ad340eSHenning Colliander 	kvaser_pciefd_pwm_stop(can);
59126ad340eSHenning Colliander 	spin_lock_irqsave(&can->lock, irq);
59226ad340eSHenning Colliander 	/* Set frequency to 500 KHz */
593ec44dd57SChrister Beskow 	top = can->kv_pcie->bus_freq / (2 * 500000) - 1;
59426ad340eSHenning Colliander 
595954fb212SJimmy Assarsson 	pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top);
596954fb212SJimmy Assarsson 	pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top);
59726ad340eSHenning Colliander 	iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
59826ad340eSHenning Colliander 
59926ad340eSHenning Colliander 	/* Set duty cycle to 95 */
60026ad340eSHenning Colliander 	trigger = (100 * top - 95 * (top + 1) + 50) / 100;
601954fb212SJimmy Assarsson 	pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, trigger);
602954fb212SJimmy Assarsson 	pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top);
60326ad340eSHenning Colliander 	iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
60426ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->lock, irq);
60526ad340eSHenning Colliander }
60626ad340eSHenning Colliander 
60726ad340eSHenning Colliander static int kvaser_pciefd_open(struct net_device *netdev)
60826ad340eSHenning Colliander {
60926ad340eSHenning Colliander 	int err;
61026ad340eSHenning Colliander 	struct kvaser_pciefd_can *can = netdev_priv(netdev);
61126ad340eSHenning Colliander 
61226ad340eSHenning Colliander 	err = open_candev(netdev);
61326ad340eSHenning Colliander 	if (err)
61426ad340eSHenning Colliander 		return err;
61526ad340eSHenning Colliander 
61626ad340eSHenning Colliander 	err = kvaser_pciefd_bus_on(can);
61713a84cf3SZhang Qilong 	if (err) {
61813a84cf3SZhang Qilong 		close_candev(netdev);
61926ad340eSHenning Colliander 		return err;
62013a84cf3SZhang Qilong 	}
62126ad340eSHenning Colliander 
62226ad340eSHenning Colliander 	return 0;
62326ad340eSHenning Colliander }
62426ad340eSHenning Colliander 
62526ad340eSHenning Colliander static int kvaser_pciefd_stop(struct net_device *netdev)
62626ad340eSHenning Colliander {
62726ad340eSHenning Colliander 	struct kvaser_pciefd_can *can = netdev_priv(netdev);
62826ad340eSHenning Colliander 	int ret = 0;
62926ad340eSHenning Colliander 
63026ad340eSHenning Colliander 	/* Don't interrupt ongoing flush */
63126ad340eSHenning Colliander 	if (!completion_done(&can->flush_comp))
63226ad340eSHenning Colliander 		kvaser_pciefd_start_controller_flush(can);
63326ad340eSHenning Colliander 
63426ad340eSHenning Colliander 	if (!wait_for_completion_timeout(&can->flush_comp,
63526ad340eSHenning Colliander 					 KVASER_PCIEFD_WAIT_TIMEOUT)) {
63626ad340eSHenning Colliander 		netdev_err(can->can.dev, "Timeout during stop\n");
63726ad340eSHenning Colliander 		ret = -ETIMEDOUT;
63826ad340eSHenning Colliander 	} else {
63926ad340eSHenning Colliander 		iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
64026ad340eSHenning Colliander 		del_timer(&can->bec_poll_timer);
64126ad340eSHenning Colliander 	}
642aed0e6caSJimmy Assarsson 	can->can.state = CAN_STATE_STOPPED;
64326ad340eSHenning Colliander 	close_candev(netdev);
64426ad340eSHenning Colliander 
64526ad340eSHenning Colliander 	return ret;
64626ad340eSHenning Colliander }
64726ad340eSHenning Colliander 
64826ad340eSHenning Colliander static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p,
64926ad340eSHenning Colliander 					   struct kvaser_pciefd_can *can,
65026ad340eSHenning Colliander 					   struct sk_buff *skb)
65126ad340eSHenning Colliander {
65226ad340eSHenning Colliander 	struct canfd_frame *cf = (struct canfd_frame *)skb->data;
65326ad340eSHenning Colliander 	int packet_size;
65426ad340eSHenning Colliander 	int seq = can->echo_idx;
65526ad340eSHenning Colliander 
65626ad340eSHenning Colliander 	memset(p, 0, sizeof(*p));
65726ad340eSHenning Colliander 	if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
65826ad340eSHenning Colliander 		p->header[1] |= KVASER_PCIEFD_TPACKET_SMS;
65926ad340eSHenning Colliander 
66026ad340eSHenning Colliander 	if (cf->can_id & CAN_RTR_FLAG)
66126ad340eSHenning Colliander 		p->header[0] |= KVASER_PCIEFD_RPACKET_RTR;
66226ad340eSHenning Colliander 
66326ad340eSHenning Colliander 	if (cf->can_id & CAN_EFF_FLAG)
66426ad340eSHenning Colliander 		p->header[0] |= KVASER_PCIEFD_RPACKET_IDE;
66526ad340eSHenning Colliander 
666954fb212SJimmy Assarsson 	p->header[0] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_ID_MASK, cf->can_id);
66726ad340eSHenning Colliander 	p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ;
66826ad340eSHenning Colliander 
66926ad340eSHenning Colliander 	if (can_is_canfd_skb(skb)) {
670f07008a2SJimmy Assarsson 		p->header[1] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK,
671f07008a2SJimmy Assarsson 					   can_fd_len2dlc(cf->len));
67226ad340eSHenning Colliander 		p->header[1] |= KVASER_PCIEFD_RPACKET_FDF;
67326ad340eSHenning Colliander 		if (cf->flags & CANFD_BRS)
67426ad340eSHenning Colliander 			p->header[1] |= KVASER_PCIEFD_RPACKET_BRS;
67526ad340eSHenning Colliander 		if (cf->flags & CANFD_ESI)
67626ad340eSHenning Colliander 			p->header[1] |= KVASER_PCIEFD_RPACKET_ESI;
677f07008a2SJimmy Assarsson 	} else {
678f07008a2SJimmy Assarsson 		p->header[1] |=
679f07008a2SJimmy Assarsson 			FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK,
680f07008a2SJimmy Assarsson 				   can_get_cc_dlc((struct can_frame *)cf, can->can.ctrlmode));
68126ad340eSHenning Colliander 	}
68226ad340eSHenning Colliander 
683954fb212SJimmy Assarsson 	p->header[1] |= FIELD_PREP(KVASER_PCIEFD_PACKET_SEQ_MASK, seq);
68426ad340eSHenning Colliander 
68526ad340eSHenning Colliander 	packet_size = cf->len;
68626ad340eSHenning Colliander 	memcpy(p->data, cf->data, packet_size);
68726ad340eSHenning Colliander 
68826ad340eSHenning Colliander 	return DIV_ROUND_UP(packet_size, 4);
68926ad340eSHenning Colliander }
69026ad340eSHenning Colliander 
69126ad340eSHenning Colliander static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
69226ad340eSHenning Colliander 					    struct net_device *netdev)
69326ad340eSHenning Colliander {
69426ad340eSHenning Colliander 	struct kvaser_pciefd_can *can = netdev_priv(netdev);
69526ad340eSHenning Colliander 	unsigned long irq_flags;
69626ad340eSHenning Colliander 	struct kvaser_pciefd_tx_packet packet;
697f4845741SJimmy Assarsson 	int nr_words;
69826ad340eSHenning Colliander 	u8 count;
69926ad340eSHenning Colliander 
700ae64438bSOliver Hartkopp 	if (can_dev_dropped_skb(netdev, skb))
70126ad340eSHenning Colliander 		return NETDEV_TX_OK;
70226ad340eSHenning Colliander 
703f4845741SJimmy Assarsson 	nr_words = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
70426ad340eSHenning Colliander 
70526ad340eSHenning Colliander 	spin_lock_irqsave(&can->echo_lock, irq_flags);
70626ad340eSHenning Colliander 	/* Prepare and save echo skb in internal slot */
7071dcb6e57SVincent Mailhol 	can_put_echo_skb(skb, netdev, can->echo_idx, 0);
70826ad340eSHenning Colliander 
70926ad340eSHenning Colliander 	/* Move echo index to the next slot */
71026ad340eSHenning Colliander 	can->echo_idx = (can->echo_idx + 1) % can->can.echo_skb_max;
71126ad340eSHenning Colliander 
71226ad340eSHenning Colliander 	/* Write header to fifo */
71326ad340eSHenning Colliander 	iowrite32(packet.header[0],
71426ad340eSHenning Colliander 		  can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG);
71526ad340eSHenning Colliander 	iowrite32(packet.header[1],
71626ad340eSHenning Colliander 		  can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG);
71726ad340eSHenning Colliander 
718f4845741SJimmy Assarsson 	if (nr_words) {
719f4845741SJimmy Assarsson 		u32 data_last = ((u32 *)packet.data)[nr_words - 1];
72026ad340eSHenning Colliander 
72126ad340eSHenning Colliander 		/* Write data to fifo, except last word */
72226ad340eSHenning Colliander 		iowrite32_rep(can->reg_base +
72326ad340eSHenning Colliander 			      KVASER_PCIEFD_KCAN_FIFO_REG, packet.data,
724f4845741SJimmy Assarsson 			      nr_words - 1);
72526ad340eSHenning Colliander 		/* Write last word to end of fifo */
72626ad340eSHenning Colliander 		__raw_writel(data_last, can->reg_base +
72726ad340eSHenning Colliander 			     KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
72826ad340eSHenning Colliander 	} else {
72926ad340eSHenning Colliander 		/* Complete write to fifo */
73026ad340eSHenning Colliander 		__raw_writel(0, can->reg_base +
73126ad340eSHenning Colliander 			     KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
73226ad340eSHenning Colliander 	}
73326ad340eSHenning Colliander 
734954fb212SJimmy Assarsson 	count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
735f4845741SJimmy Assarsson 			  ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
73626ad340eSHenning Colliander 	/* No room for a new message, stop the queue until at least one
73726ad340eSHenning Colliander 	 * successful transmit
73826ad340eSHenning Colliander 	 */
7396fdcd64eSJimmy Assarsson 	if (count >= can->can.echo_skb_max || can->can.echo_skb[can->echo_idx])
74026ad340eSHenning Colliander 		netif_stop_queue(netdev);
74126ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->echo_lock, irq_flags);
74226ad340eSHenning Colliander 
74326ad340eSHenning Colliander 	return NETDEV_TX_OK;
74426ad340eSHenning Colliander }
74526ad340eSHenning Colliander 
74626ad340eSHenning Colliander static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
74726ad340eSHenning Colliander {
74826ad340eSHenning Colliander 	u32 mode, test, btrn;
74926ad340eSHenning Colliander 	unsigned long irq_flags;
75026ad340eSHenning Colliander 	int ret;
75126ad340eSHenning Colliander 	struct can_bittiming *bt;
75226ad340eSHenning Colliander 
75326ad340eSHenning Colliander 	if (data)
75426ad340eSHenning Colliander 		bt = &can->can.data_bittiming;
75526ad340eSHenning Colliander 	else
75626ad340eSHenning Colliander 		bt = &can->can.bittiming;
75726ad340eSHenning Colliander 
758954fb212SJimmy Assarsson 	btrn = FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK, bt->phase_seg2 - 1) |
759954fb212SJimmy Assarsson 	       FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK, bt->prop_seg + bt->phase_seg1 - 1) |
760954fb212SJimmy Assarsson 	       FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_SJW_MASK, bt->sjw - 1) |
761954fb212SJimmy Assarsson 	       FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_BRP_MASK, bt->brp - 1);
76226ad340eSHenning Colliander 
76326ad340eSHenning Colliander 	spin_lock_irqsave(&can->lock, irq_flags);
76426ad340eSHenning Colliander 	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
76526ad340eSHenning Colliander 	/* Put the circuit in reset mode */
76626ad340eSHenning Colliander 	iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM,
76726ad340eSHenning Colliander 		  can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
76826ad340eSHenning Colliander 
76926ad340eSHenning Colliander 	/* Can only set bittiming if in reset mode */
77026ad340eSHenning Colliander 	ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG,
771f4845741SJimmy Assarsson 				 test, test & KVASER_PCIEFD_KCAN_MODE_RM, 0, 10);
77226ad340eSHenning Colliander 	if (ret) {
77326ad340eSHenning Colliander 		spin_unlock_irqrestore(&can->lock, irq_flags);
77426ad340eSHenning Colliander 		return -EBUSY;
77526ad340eSHenning Colliander 	}
77626ad340eSHenning Colliander 
77726ad340eSHenning Colliander 	if (data)
77826ad340eSHenning Colliander 		iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG);
77926ad340eSHenning Colliander 	else
78026ad340eSHenning Colliander 		iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG);
78126ad340eSHenning Colliander 	/* Restore previous reset mode status */
78226ad340eSHenning Colliander 	iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
78326ad340eSHenning Colliander 	spin_unlock_irqrestore(&can->lock, irq_flags);
784f4845741SJimmy Assarsson 
78526ad340eSHenning Colliander 	return 0;
78626ad340eSHenning Colliander }
78726ad340eSHenning Colliander 
78826ad340eSHenning Colliander static int kvaser_pciefd_set_nominal_bittiming(struct net_device *ndev)
78926ad340eSHenning Colliander {
79026ad340eSHenning Colliander 	return kvaser_pciefd_set_bittiming(netdev_priv(ndev), false);
79126ad340eSHenning Colliander }
79226ad340eSHenning Colliander 
79326ad340eSHenning Colliander static int kvaser_pciefd_set_data_bittiming(struct net_device *ndev)
79426ad340eSHenning Colliander {
79526ad340eSHenning Colliander 	return kvaser_pciefd_set_bittiming(netdev_priv(ndev), true);
79626ad340eSHenning Colliander }
79726ad340eSHenning Colliander 
79826ad340eSHenning Colliander static int kvaser_pciefd_set_mode(struct net_device *ndev, enum can_mode mode)
79926ad340eSHenning Colliander {
80026ad340eSHenning Colliander 	struct kvaser_pciefd_can *can = netdev_priv(ndev);
80126ad340eSHenning Colliander 	int ret = 0;
80226ad340eSHenning Colliander 
80326ad340eSHenning Colliander 	switch (mode) {
80426ad340eSHenning Colliander 	case CAN_MODE_START:
80526ad340eSHenning Colliander 		if (!can->can.restart_ms)
80626ad340eSHenning Colliander 			ret = kvaser_pciefd_bus_on(can);
80726ad340eSHenning Colliander 		break;
80826ad340eSHenning Colliander 	default:
80926ad340eSHenning Colliander 		return -EOPNOTSUPP;
81026ad340eSHenning Colliander 	}
81126ad340eSHenning Colliander 
81226ad340eSHenning Colliander 	return ret;
81326ad340eSHenning Colliander }
81426ad340eSHenning Colliander 
81526ad340eSHenning Colliander static int kvaser_pciefd_get_berr_counter(const struct net_device *ndev,
81626ad340eSHenning Colliander 					  struct can_berr_counter *bec)
81726ad340eSHenning Colliander {
81826ad340eSHenning Colliander 	struct kvaser_pciefd_can *can = netdev_priv(ndev);
81926ad340eSHenning Colliander 
82026ad340eSHenning Colliander 	bec->rxerr = can->bec.rxerr;
82126ad340eSHenning Colliander 	bec->txerr = can->bec.txerr;
822f4845741SJimmy Assarsson 
82326ad340eSHenning Colliander 	return 0;
82426ad340eSHenning Colliander }
82526ad340eSHenning Colliander 
82626ad340eSHenning Colliander static void kvaser_pciefd_bec_poll_timer(struct timer_list *data)
82726ad340eSHenning Colliander {
82826ad340eSHenning Colliander 	struct kvaser_pciefd_can *can = from_timer(can, data, bec_poll_timer);
82926ad340eSHenning Colliander 
83026ad340eSHenning Colliander 	kvaser_pciefd_enable_err_gen(can);
83126ad340eSHenning Colliander 	kvaser_pciefd_request_status(can);
83226ad340eSHenning Colliander 	can->err_rep_cnt = 0;
83326ad340eSHenning Colliander }
83426ad340eSHenning Colliander 
83526ad340eSHenning Colliander static const struct net_device_ops kvaser_pciefd_netdev_ops = {
83626ad340eSHenning Colliander 	.ndo_open = kvaser_pciefd_open,
83726ad340eSHenning Colliander 	.ndo_stop = kvaser_pciefd_stop,
838fa5cc7e1SVincent Mailhol 	.ndo_eth_ioctl = can_eth_ioctl_hwts,
83926ad340eSHenning Colliander 	.ndo_start_xmit = kvaser_pciefd_start_xmit,
84026ad340eSHenning Colliander 	.ndo_change_mtu = can_change_mtu,
84126ad340eSHenning Colliander };
84226ad340eSHenning Colliander 
843fa5cc7e1SVincent Mailhol static const struct ethtool_ops kvaser_pciefd_ethtool_ops = {
844fa5cc7e1SVincent Mailhol 	.get_ts_info = can_ethtool_op_get_ts_info_hwts,
845fa5cc7e1SVincent Mailhol };
846fa5cc7e1SVincent Mailhol 
84726ad340eSHenning Colliander static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
84826ad340eSHenning Colliander {
84926ad340eSHenning Colliander 	int i;
85026ad340eSHenning Colliander 
85126ad340eSHenning Colliander 	for (i = 0; i < pcie->nr_channels; i++) {
85226ad340eSHenning Colliander 		struct net_device *netdev;
85326ad340eSHenning Colliander 		struct kvaser_pciefd_can *can;
854954fb212SJimmy Assarsson 		u32 status, tx_nr_packets_max;
85526ad340eSHenning Colliander 
85626ad340eSHenning Colliander 		netdev = alloc_candev(sizeof(struct kvaser_pciefd_can),
85726ad340eSHenning Colliander 				      KVASER_PCIEFD_CAN_TX_MAX_COUNT);
85826ad340eSHenning Colliander 		if (!netdev)
85926ad340eSHenning Colliander 			return -ENOMEM;
86026ad340eSHenning Colliander 
86126ad340eSHenning Colliander 		can = netdev_priv(netdev);
86226ad340eSHenning Colliander 		netdev->netdev_ops = &kvaser_pciefd_netdev_ops;
863fa5cc7e1SVincent Mailhol 		netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops;
864*c2ad8129SJimmy Assarsson 		can->reg_base = KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i);
86526ad340eSHenning Colliander 		can->kv_pcie = pcie;
86626ad340eSHenning Colliander 		can->cmd_seq = 0;
86726ad340eSHenning Colliander 		can->err_rep_cnt = 0;
86826ad340eSHenning Colliander 		can->bec.txerr = 0;
86926ad340eSHenning Colliander 		can->bec.rxerr = 0;
87026ad340eSHenning Colliander 
87126ad340eSHenning Colliander 		init_completion(&can->start_comp);
87226ad340eSHenning Colliander 		init_completion(&can->flush_comp);
873f4845741SJimmy Assarsson 		timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 0);
87426ad340eSHenning Colliander 
8757c6e6bceSJimmy Assarsson 		/* Disable Bus load reporting */
8767c6e6bceSJimmy Assarsson 		iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG);
8777c6e6bceSJimmy Assarsson 
878954fb212SJimmy Assarsson 		tx_nr_packets_max =
879954fb212SJimmy Assarsson 			FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK,
880f4845741SJimmy Assarsson 				  ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
88126ad340eSHenning Colliander 
88226ad340eSHenning Colliander 		can->can.clock.freq = pcie->freq;
8836fdcd64eSJimmy Assarsson 		can->can.echo_skb_max = min(KVASER_PCIEFD_CAN_TX_MAX_COUNT, tx_nr_packets_max - 1);
88426ad340eSHenning Colliander 		can->echo_idx = 0;
88526ad340eSHenning Colliander 		spin_lock_init(&can->echo_lock);
88626ad340eSHenning Colliander 		spin_lock_init(&can->lock);
887f4845741SJimmy Assarsson 
88826ad340eSHenning Colliander 		can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
88926ad340eSHenning Colliander 		can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const;
89026ad340eSHenning Colliander 		can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
891f4845741SJimmy Assarsson 		can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
89226ad340eSHenning Colliander 		can->can.do_set_mode = kvaser_pciefd_set_mode;
89326ad340eSHenning Colliander 		can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
89426ad340eSHenning Colliander 		can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
89526ad340eSHenning Colliander 					      CAN_CTRLMODE_FD |
896f07008a2SJimmy Assarsson 					      CAN_CTRLMODE_FD_NON_ISO |
897f07008a2SJimmy Assarsson 					      CAN_CTRLMODE_CC_LEN8_DLC;
89826ad340eSHenning Colliander 
89926ad340eSHenning Colliander 		status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
90026ad340eSHenning Colliander 		if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) {
90126ad340eSHenning Colliander 			dev_err(&pcie->pci->dev,
90226ad340eSHenning Colliander 				"CAN FD not supported as expected %d\n", i);
90326ad340eSHenning Colliander 
90426ad340eSHenning Colliander 			free_candev(netdev);
90526ad340eSHenning Colliander 			return -ENODEV;
90626ad340eSHenning Colliander 		}
90726ad340eSHenning Colliander 
90826ad340eSHenning Colliander 		if (status & KVASER_PCIEFD_KCAN_STAT_CAP)
90926ad340eSHenning Colliander 			can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
91026ad340eSHenning Colliander 
91126ad340eSHenning Colliander 		netdev->flags |= IFF_ECHO;
91226ad340eSHenning Colliander 		SET_NETDEV_DEV(netdev, &pcie->pci->dev);
91326ad340eSHenning Colliander 
914f4845741SJimmy Assarsson 		iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
915262d7a52SJimmy Assarsson 		iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
91626ad340eSHenning Colliander 			  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
91726ad340eSHenning Colliander 
91826ad340eSHenning Colliander 		pcie->can[i] = can;
91926ad340eSHenning Colliander 		kvaser_pciefd_pwm_start(can);
92026ad340eSHenning Colliander 	}
92126ad340eSHenning Colliander 
92226ad340eSHenning Colliander 	return 0;
92326ad340eSHenning Colliander }
92426ad340eSHenning Colliander 
92526ad340eSHenning Colliander static int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie)
92626ad340eSHenning Colliander {
92726ad340eSHenning Colliander 	int i;
92826ad340eSHenning Colliander 
92926ad340eSHenning Colliander 	for (i = 0; i < pcie->nr_channels; i++) {
93026ad340eSHenning Colliander 		int err = register_candev(pcie->can[i]->can.dev);
93126ad340eSHenning Colliander 
93226ad340eSHenning Colliander 		if (err) {
93326ad340eSHenning Colliander 			int j;
93426ad340eSHenning Colliander 
93526ad340eSHenning Colliander 			/* Unregister all successfully registered devices. */
93626ad340eSHenning Colliander 			for (j = 0; j < i; j++)
93726ad340eSHenning Colliander 				unregister_candev(pcie->can[j]->can.dev);
93826ad340eSHenning Colliander 			return err;
93926ad340eSHenning Colliander 		}
94026ad340eSHenning Colliander 	}
94126ad340eSHenning Colliander 
94226ad340eSHenning Colliander 	return 0;
94326ad340eSHenning Colliander }
94426ad340eSHenning Colliander 
945*c2ad8129SJimmy Assarsson static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie,
946*c2ad8129SJimmy Assarsson 					       dma_addr_t addr, int index)
94726ad340eSHenning Colliander {
948*c2ad8129SJimmy Assarsson 	void __iomem *serdes_base;
94926ad340eSHenning Colliander 	u32 word1, word2;
95026ad340eSHenning Colliander 
95126ad340eSHenning Colliander #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
952*c2ad8129SJimmy Assarsson 	word1 = addr | KVASER_PCIEFD_ALTERA_DMA_64BIT;
95326ad340eSHenning Colliander 	word2 = addr >> 32;
95426ad340eSHenning Colliander #else
95526ad340eSHenning Colliander 	word1 = addr;
95626ad340eSHenning Colliander 	word2 = 0;
95726ad340eSHenning Colliander #endif
958*c2ad8129SJimmy Assarsson 	serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x8 * index;
959*c2ad8129SJimmy Assarsson 	iowrite32(word1, serdes_base);
960*c2ad8129SJimmy Assarsson 	iowrite32(word2, serdes_base + 0x4);
96126ad340eSHenning Colliander }
96226ad340eSHenning Colliander 
96326ad340eSHenning Colliander static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
96426ad340eSHenning Colliander {
96526ad340eSHenning Colliander 	int i;
96626ad340eSHenning Colliander 	u32 srb_status;
967c589557dSJimmy Assarsson 	u32 srb_packet_count;
96826ad340eSHenning Colliander 	dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT];
96926ad340eSHenning Colliander 
97026ad340eSHenning Colliander 	/* Disable the DMA */
971*c2ad8129SJimmy Assarsson 	iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
97226ad340eSHenning Colliander 	for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) {
973f4845741SJimmy Assarsson 		pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev,
97426ad340eSHenning Colliander 							KVASER_PCIEFD_DMA_SIZE,
97526ad340eSHenning Colliander 							&dma_addr[i],
97626ad340eSHenning Colliander 							GFP_KERNEL);
97726ad340eSHenning Colliander 
97826ad340eSHenning Colliander 		if (!pcie->dma_data[i] || !dma_addr[i]) {
97926ad340eSHenning Colliander 			dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n",
98026ad340eSHenning Colliander 				KVASER_PCIEFD_DMA_SIZE);
98126ad340eSHenning Colliander 			return -ENOMEM;
98226ad340eSHenning Colliander 		}
983*c2ad8129SJimmy Assarsson 		pcie->driver_data->ops->kvaser_pciefd_write_dma_map(pcie, dma_addr[i], i);
98426ad340eSHenning Colliander 	}
98526ad340eSHenning Colliander 
98626ad340eSHenning Colliander 	/* Reset Rx FIFO, and both DMA buffers */
98726ad340eSHenning Colliander 	iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 |
98826ad340eSHenning Colliander 		  KVASER_PCIEFD_SRB_CMD_RDB1,
989*c2ad8129SJimmy Assarsson 		  KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
990c589557dSJimmy Assarsson 	/* Empty Rx FIFO */
991954fb212SJimmy Assarsson 	srb_packet_count =
992954fb212SJimmy Assarsson 		FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK,
993*c2ad8129SJimmy Assarsson 			  ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) +
994*c2ad8129SJimmy Assarsson 				   KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG));
995c589557dSJimmy Assarsson 	while (srb_packet_count) {
996c589557dSJimmy Assarsson 		/* Drop current packet in FIFO */
997*c2ad8129SJimmy Assarsson 		ioread32(KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
998c589557dSJimmy Assarsson 		srb_packet_count--;
999c589557dSJimmy Assarsson 	}
1000c589557dSJimmy Assarsson 
1001*c2ad8129SJimmy Assarsson 	srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG);
100226ad340eSHenning Colliander 	if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) {
100326ad340eSHenning Colliander 		dev_err(&pcie->pci->dev, "DMA not idle before enabling\n");
100426ad340eSHenning Colliander 		return -EIO;
100526ad340eSHenning Colliander 	}
100626ad340eSHenning Colliander 
100726ad340eSHenning Colliander 	/* Enable the DMA */
100826ad340eSHenning Colliander 	iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE,
1009*c2ad8129SJimmy Assarsson 		  KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
101026ad340eSHenning Colliander 
101126ad340eSHenning Colliander 	return 0;
101226ad340eSHenning Colliander }
101326ad340eSHenning Colliander 
101426ad340eSHenning Colliander static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie)
101526ad340eSHenning Colliander {
1016954fb212SJimmy Assarsson 	u32 version, srb_status, build;
101726ad340eSHenning Colliander 
1018*c2ad8129SJimmy Assarsson 	version = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_VERSION_REG);
1019c496adafSJimmy Assarsson 	pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS,
1020954fb212SJimmy Assarsson 				FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version));
102126ad340eSHenning Colliander 
1022*c2ad8129SJimmy Assarsson 	build = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUILD_REG);
1023954fb212SJimmy Assarsson 	dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n",
1024954fb212SJimmy Assarsson 		FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version),
1025954fb212SJimmy Assarsson 		FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version),
1026954fb212SJimmy Assarsson 		FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build));
102726ad340eSHenning Colliander 
1028*c2ad8129SJimmy Assarsson 	srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG);
102926ad340eSHenning Colliander 	if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) {
1030f4845741SJimmy Assarsson 		dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n");
103126ad340eSHenning Colliander 		return -ENODEV;
103226ad340eSHenning Colliander 	}
103326ad340eSHenning Colliander 
1034*c2ad8129SJimmy Assarsson 	pcie->bus_freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUSFREQ_REG);
1035*c2ad8129SJimmy Assarsson 	pcie->freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_CANFREQ_REG);
103626ad340eSHenning Colliander 	pcie->freq_to_ticks_div = pcie->freq / 1000000;
103726ad340eSHenning Colliander 	if (pcie->freq_to_ticks_div == 0)
103826ad340eSHenning Colliander 		pcie->freq_to_ticks_div = 1;
103926ad340eSHenning Colliander 	/* Turn off all loopback functionality */
1040*c2ad8129SJimmy Assarsson 	iowrite32(0, KVASER_PCIEFD_LOOPBACK_ADDR(pcie));
1041f4845741SJimmy Assarsson 
1042c496adafSJimmy Assarsson 	return 0;
104326ad340eSHenning Colliander }
104426ad340eSHenning Colliander 
104526ad340eSHenning Colliander static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
104626ad340eSHenning Colliander 					    struct kvaser_pciefd_rx_packet *p,
104726ad340eSHenning Colliander 					    __le32 *data)
104826ad340eSHenning Colliander {
104926ad340eSHenning Colliander 	struct sk_buff *skb;
105026ad340eSHenning Colliander 	struct canfd_frame *cf;
105126ad340eSHenning Colliander 	struct can_priv *priv;
1052954fb212SJimmy Assarsson 	u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
1053f07008a2SJimmy Assarsson 	u8 dlc;
105426ad340eSHenning Colliander 
105526ad340eSHenning Colliander 	if (ch_id >= pcie->nr_channels)
105626ad340eSHenning Colliander 		return -EIO;
105726ad340eSHenning Colliander 
105826ad340eSHenning Colliander 	priv = &pcie->can[ch_id]->can;
1059f07008a2SJimmy Assarsson 	dlc = FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, p->header[1]);
106026ad340eSHenning Colliander 
106126ad340eSHenning Colliander 	if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) {
106226ad340eSHenning Colliander 		skb = alloc_canfd_skb(priv->dev, &cf);
106326ad340eSHenning Colliander 		if (!skb) {
1064f4845741SJimmy Assarsson 			priv->dev->stats.rx_dropped++;
106526ad340eSHenning Colliander 			return -ENOMEM;
106626ad340eSHenning Colliander 		}
106726ad340eSHenning Colliander 
1068f07008a2SJimmy Assarsson 		cf->len = can_fd_dlc2len(dlc);
106926ad340eSHenning Colliander 		if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS)
107026ad340eSHenning Colliander 			cf->flags |= CANFD_BRS;
107126ad340eSHenning Colliander 		if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI)
107226ad340eSHenning Colliander 			cf->flags |= CANFD_ESI;
107326ad340eSHenning Colliander 	} else {
107426ad340eSHenning Colliander 		skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf);
107526ad340eSHenning Colliander 		if (!skb) {
1076f4845741SJimmy Assarsson 			priv->dev->stats.rx_dropped++;
107726ad340eSHenning Colliander 			return -ENOMEM;
107826ad340eSHenning Colliander 		}
1079f07008a2SJimmy Assarsson 		can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->ctrlmode);
108026ad340eSHenning Colliander 	}
108126ad340eSHenning Colliander 
1082954fb212SJimmy Assarsson 	cf->can_id = FIELD_GET(KVASER_PCIEFD_RPACKET_ID_MASK, p->header[0]);
108326ad340eSHenning Colliander 	if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE)
108426ad340eSHenning Colliander 		cf->can_id |= CAN_EFF_FLAG;
108526ad340eSHenning Colliander 
10868e674ca7SVincent Mailhol 	if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) {
108726ad340eSHenning Colliander 		cf->can_id |= CAN_RTR_FLAG;
10888e674ca7SVincent Mailhol 	} else {
108926ad340eSHenning Colliander 		memcpy(cf->data, data, cf->len);
1090f4845741SJimmy Assarsson 		priv->dev->stats.rx_bytes += cf->len;
10918e674ca7SVincent Mailhol 	}
1092f4845741SJimmy Assarsson 	priv->dev->stats.rx_packets++;
10932d55e9f9SJimmy Assarsson 	kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp);
109426ad340eSHenning Colliander 
109526ad340eSHenning Colliander 	return netif_rx(skb);
109626ad340eSHenning Colliander }
109726ad340eSHenning Colliander 
109826ad340eSHenning Colliander static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
109926ad340eSHenning Colliander 				       struct can_frame *cf,
110026ad340eSHenning Colliander 				       enum can_state new_state,
110126ad340eSHenning Colliander 				       enum can_state tx_state,
110226ad340eSHenning Colliander 				       enum can_state rx_state)
110326ad340eSHenning Colliander {
110426ad340eSHenning Colliander 	can_change_state(can->can.dev, cf, tx_state, rx_state);
110526ad340eSHenning Colliander 
110626ad340eSHenning Colliander 	if (new_state == CAN_STATE_BUS_OFF) {
110726ad340eSHenning Colliander 		struct net_device *ndev = can->can.dev;
110826ad340eSHenning Colliander 		unsigned long irq_flags;
110926ad340eSHenning Colliander 
111026ad340eSHenning Colliander 		spin_lock_irqsave(&can->lock, irq_flags);
111126ad340eSHenning Colliander 		netif_stop_queue(can->can.dev);
111226ad340eSHenning Colliander 		spin_unlock_irqrestore(&can->lock, irq_flags);
111326ad340eSHenning Colliander 		/* Prevent CAN controller from auto recover from bus off */
111426ad340eSHenning Colliander 		if (!can->can.restart_ms) {
111526ad340eSHenning Colliander 			kvaser_pciefd_start_controller_flush(can);
111626ad340eSHenning Colliander 			can_bus_off(ndev);
111726ad340eSHenning Colliander 		}
111826ad340eSHenning Colliander 	}
111926ad340eSHenning Colliander }
112026ad340eSHenning Colliander 
112126ad340eSHenning Colliander static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p,
112226ad340eSHenning Colliander 					  struct can_berr_counter *bec,
112326ad340eSHenning Colliander 					  enum can_state *new_state,
112426ad340eSHenning Colliander 					  enum can_state *tx_state,
112526ad340eSHenning Colliander 					  enum can_state *rx_state)
112626ad340eSHenning Colliander {
112726ad340eSHenning Colliander 	if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF ||
112826ad340eSHenning Colliander 	    p->header[0] & KVASER_PCIEFD_SPACK_IRM)
112926ad340eSHenning Colliander 		*new_state = CAN_STATE_BUS_OFF;
113026ad340eSHenning Colliander 	else if (bec->txerr >= 255 || bec->rxerr >= 255)
113126ad340eSHenning Colliander 		*new_state = CAN_STATE_BUS_OFF;
113226ad340eSHenning Colliander 	else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR)
113326ad340eSHenning Colliander 		*new_state = CAN_STATE_ERROR_PASSIVE;
113426ad340eSHenning Colliander 	else if (bec->txerr >= 128 || bec->rxerr >= 128)
113526ad340eSHenning Colliander 		*new_state = CAN_STATE_ERROR_PASSIVE;
113626ad340eSHenning Colliander 	else if (p->header[1] & KVASER_PCIEFD_SPACK_EWLR)
113726ad340eSHenning Colliander 		*new_state = CAN_STATE_ERROR_WARNING;
113826ad340eSHenning Colliander 	else if (bec->txerr >= 96 || bec->rxerr >= 96)
113926ad340eSHenning Colliander 		*new_state = CAN_STATE_ERROR_WARNING;
114026ad340eSHenning Colliander 	else
114126ad340eSHenning Colliander 		*new_state = CAN_STATE_ERROR_ACTIVE;
114226ad340eSHenning Colliander 
114326ad340eSHenning Colliander 	*tx_state = bec->txerr >= bec->rxerr ? *new_state : 0;
114426ad340eSHenning Colliander 	*rx_state = bec->txerr <= bec->rxerr ? *new_state : 0;
114526ad340eSHenning Colliander }
114626ad340eSHenning Colliander 
114726ad340eSHenning Colliander static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
114826ad340eSHenning Colliander 					struct kvaser_pciefd_rx_packet *p)
114926ad340eSHenning Colliander {
115026ad340eSHenning Colliander 	struct can_berr_counter bec;
115126ad340eSHenning Colliander 	enum can_state old_state, new_state, tx_state, rx_state;
115226ad340eSHenning Colliander 	struct net_device *ndev = can->can.dev;
115326ad340eSHenning Colliander 	struct sk_buff *skb;
115426ad340eSHenning Colliander 	struct can_frame *cf = NULL;
115526ad340eSHenning Colliander 
115626ad340eSHenning Colliander 	old_state = can->can.state;
115726ad340eSHenning Colliander 
1158954fb212SJimmy Assarsson 	bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]);
1159954fb212SJimmy Assarsson 	bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
116026ad340eSHenning Colliander 
1161f4845741SJimmy Assarsson 	kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
116226ad340eSHenning Colliander 	skb = alloc_can_err_skb(ndev, &cf);
116326ad340eSHenning Colliander 	if (new_state != old_state) {
1164f4845741SJimmy Assarsson 		kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
116526ad340eSHenning Colliander 		if (old_state == CAN_STATE_BUS_OFF &&
116626ad340eSHenning Colliander 		    new_state == CAN_STATE_ERROR_ACTIVE &&
116726ad340eSHenning Colliander 		    can->can.restart_ms) {
116826ad340eSHenning Colliander 			can->can.can_stats.restarts++;
116926ad340eSHenning Colliander 			if (skb)
117026ad340eSHenning Colliander 				cf->can_id |= CAN_ERR_RESTARTED;
117126ad340eSHenning Colliander 		}
117226ad340eSHenning Colliander 	}
117326ad340eSHenning Colliander 
117426ad340eSHenning Colliander 	can->err_rep_cnt++;
117526ad340eSHenning Colliander 	can->can.can_stats.bus_error++;
117636aea60fSJimmy Assarsson 	if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX)
1177f4845741SJimmy Assarsson 		ndev->stats.tx_errors++;
117836aea60fSJimmy Assarsson 	else
1179f4845741SJimmy Assarsson 		ndev->stats.rx_errors++;
118026ad340eSHenning Colliander 
118126ad340eSHenning Colliander 	can->bec.txerr = bec.txerr;
118226ad340eSHenning Colliander 	can->bec.rxerr = bec.rxerr;
118326ad340eSHenning Colliander 
118426ad340eSHenning Colliander 	if (!skb) {
1185f4845741SJimmy Assarsson 		ndev->stats.rx_dropped++;
118626ad340eSHenning Colliander 		return -ENOMEM;
118726ad340eSHenning Colliander 	}
118826ad340eSHenning Colliander 
11892d55e9f9SJimmy Assarsson 	kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
11903e5c291cSVincent Mailhol 	cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT;
119126ad340eSHenning Colliander 	cf->data[6] = bec.txerr;
119226ad340eSHenning Colliander 	cf->data[7] = bec.rxerr;
119326ad340eSHenning Colliander 
119426ad340eSHenning Colliander 	netif_rx(skb);
1195f4845741SJimmy Assarsson 
119626ad340eSHenning Colliander 	return 0;
119726ad340eSHenning Colliander }
119826ad340eSHenning Colliander 
119926ad340eSHenning Colliander static int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie,
120026ad340eSHenning Colliander 					     struct kvaser_pciefd_rx_packet *p)
120126ad340eSHenning Colliander {
120226ad340eSHenning Colliander 	struct kvaser_pciefd_can *can;
1203954fb212SJimmy Assarsson 	u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
120426ad340eSHenning Colliander 
120526ad340eSHenning Colliander 	if (ch_id >= pcie->nr_channels)
120626ad340eSHenning Colliander 		return -EIO;
120726ad340eSHenning Colliander 
120826ad340eSHenning Colliander 	can = pcie->can[ch_id];
120926ad340eSHenning Colliander 	kvaser_pciefd_rx_error_frame(can, p);
121026ad340eSHenning Colliander 	if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP)
121126ad340eSHenning Colliander 		/* Do not report more errors, until bec_poll_timer expires */
121226ad340eSHenning Colliander 		kvaser_pciefd_disable_err_gen(can);
121326ad340eSHenning Colliander 	/* Start polling the error counters */
121426ad340eSHenning Colliander 	mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
1215f4845741SJimmy Assarsson 
121626ad340eSHenning Colliander 	return 0;
121726ad340eSHenning Colliander }
121826ad340eSHenning Colliander 
121926ad340eSHenning Colliander static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
122026ad340eSHenning Colliander 					    struct kvaser_pciefd_rx_packet *p)
122126ad340eSHenning Colliander {
122226ad340eSHenning Colliander 	struct can_berr_counter bec;
122326ad340eSHenning Colliander 	enum can_state old_state, new_state, tx_state, rx_state;
122426ad340eSHenning Colliander 
122526ad340eSHenning Colliander 	old_state = can->can.state;
122626ad340eSHenning Colliander 
1227954fb212SJimmy Assarsson 	bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]);
1228954fb212SJimmy Assarsson 	bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]);
122926ad340eSHenning Colliander 
1230f4845741SJimmy Assarsson 	kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state);
123126ad340eSHenning Colliander 	if (new_state != old_state) {
123226ad340eSHenning Colliander 		struct net_device *ndev = can->can.dev;
123326ad340eSHenning Colliander 		struct sk_buff *skb;
123426ad340eSHenning Colliander 		struct can_frame *cf;
123526ad340eSHenning Colliander 
123626ad340eSHenning Colliander 		skb = alloc_can_err_skb(ndev, &cf);
123726ad340eSHenning Colliander 		if (!skb) {
1238f4845741SJimmy Assarsson 			ndev->stats.rx_dropped++;
123926ad340eSHenning Colliander 			return -ENOMEM;
124026ad340eSHenning Colliander 		}
124126ad340eSHenning Colliander 
1242f4845741SJimmy Assarsson 		kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state);
124326ad340eSHenning Colliander 		if (old_state == CAN_STATE_BUS_OFF &&
124426ad340eSHenning Colliander 		    new_state == CAN_STATE_ERROR_ACTIVE &&
124526ad340eSHenning Colliander 		    can->can.restart_ms) {
124626ad340eSHenning Colliander 			can->can.can_stats.restarts++;
124726ad340eSHenning Colliander 			cf->can_id |= CAN_ERR_RESTARTED;
124826ad340eSHenning Colliander 		}
124926ad340eSHenning Colliander 
12502d55e9f9SJimmy Assarsson 		kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
125126ad340eSHenning Colliander 
125226ad340eSHenning Colliander 		cf->data[6] = bec.txerr;
125326ad340eSHenning Colliander 		cf->data[7] = bec.rxerr;
125426ad340eSHenning Colliander 
125526ad340eSHenning Colliander 		netif_rx(skb);
125626ad340eSHenning Colliander 	}
125726ad340eSHenning Colliander 	can->bec.txerr = bec.txerr;
125826ad340eSHenning Colliander 	can->bec.rxerr = bec.rxerr;
125926ad340eSHenning Colliander 	/* Check if we need to poll the error counters */
126026ad340eSHenning Colliander 	if (bec.txerr || bec.rxerr)
126126ad340eSHenning Colliander 		mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
126226ad340eSHenning Colliander 
126326ad340eSHenning Colliander 	return 0;
126426ad340eSHenning Colliander }
126526ad340eSHenning Colliander 
126626ad340eSHenning Colliander static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
126726ad340eSHenning Colliander 					      struct kvaser_pciefd_rx_packet *p)
126826ad340eSHenning Colliander {
126926ad340eSHenning Colliander 	struct kvaser_pciefd_can *can;
127026ad340eSHenning Colliander 	u8 cmdseq;
127126ad340eSHenning Colliander 	u32 status;
1272954fb212SJimmy Assarsson 	u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
127326ad340eSHenning Colliander 
127426ad340eSHenning Colliander 	if (ch_id >= pcie->nr_channels)
127526ad340eSHenning Colliander 		return -EIO;
127626ad340eSHenning Colliander 
127726ad340eSHenning Colliander 	can = pcie->can[ch_id];
127826ad340eSHenning Colliander 
127926ad340eSHenning Colliander 	status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
1280954fb212SJimmy Assarsson 	cmdseq = FIELD_GET(KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK, status);
128126ad340eSHenning Colliander 
128226ad340eSHenning Colliander 	/* Reset done, start abort and flush */
128326ad340eSHenning Colliander 	if (p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
128426ad340eSHenning Colliander 	    p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
128526ad340eSHenning Colliander 	    p->header[1] & KVASER_PCIEFD_SPACK_AUTO &&
1286954fb212SJimmy Assarsson 	    cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) &&
128726ad340eSHenning Colliander 	    status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
128826ad340eSHenning Colliander 		iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
128926ad340eSHenning Colliander 			  can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
1290f4845741SJimmy Assarsson 		kvaser_pciefd_abort_flush_reset(can);
129126ad340eSHenning Colliander 	} else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
129226ad340eSHenning Colliander 		   p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
1293954fb212SJimmy Assarsson 		   cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) &&
129426ad340eSHenning Colliander 		   status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
129526ad340eSHenning Colliander 		/* Reset detected, send end of flush if no packet are in FIFO */
1296f4845741SJimmy Assarsson 		u8 count;
129726ad340eSHenning Colliander 
1298f4845741SJimmy Assarsson 		count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
1299f4845741SJimmy Assarsson 				  ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
130026ad340eSHenning Colliander 		if (!count)
1301954fb212SJimmy Assarsson 			iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK,
1302954fb212SJimmy Assarsson 					     KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH),
130326ad340eSHenning Colliander 				  can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
130426ad340eSHenning Colliander 	} else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) &&
1305954fb212SJimmy Assarsson 		   cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1])) {
130626ad340eSHenning Colliander 		/* Response to status request received */
130726ad340eSHenning Colliander 		kvaser_pciefd_handle_status_resp(can, p);
130826ad340eSHenning Colliander 		if (can->can.state != CAN_STATE_BUS_OFF &&
130926ad340eSHenning Colliander 		    can->can.state != CAN_STATE_ERROR_ACTIVE) {
1310f4845741SJimmy Assarsson 			mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
131126ad340eSHenning Colliander 		}
131226ad340eSHenning Colliander 	} else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
1313f4845741SJimmy Assarsson 		   !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK)) {
131426ad340eSHenning Colliander 		/* Reset to bus on detected */
131526ad340eSHenning Colliander 		if (!completion_done(&can->start_comp))
131626ad340eSHenning Colliander 			complete(&can->start_comp);
131726ad340eSHenning Colliander 	}
131826ad340eSHenning Colliander 
131926ad340eSHenning Colliander 	return 0;
132026ad340eSHenning Colliander }
132126ad340eSHenning Colliander 
132226ad340eSHenning Colliander static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can,
132326ad340eSHenning Colliander 					     struct kvaser_pciefd_rx_packet *p)
132426ad340eSHenning Colliander {
132526ad340eSHenning Colliander 	struct sk_buff *skb;
132626ad340eSHenning Colliander 	struct can_frame *cf;
132726ad340eSHenning Colliander 
132826ad340eSHenning Colliander 	skb = alloc_can_err_skb(can->can.dev, &cf);
1329f4845741SJimmy Assarsson 	can->can.dev->stats.tx_errors++;
133026ad340eSHenning Colliander 	if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) {
133126ad340eSHenning Colliander 		if (skb)
133226ad340eSHenning Colliander 			cf->can_id |= CAN_ERR_LOSTARB;
133326ad340eSHenning Colliander 		can->can.can_stats.arbitration_lost++;
133426ad340eSHenning Colliander 	} else if (skb) {
133526ad340eSHenning Colliander 		cf->can_id |= CAN_ERR_ACK;
133626ad340eSHenning Colliander 	}
133726ad340eSHenning Colliander 
133826ad340eSHenning Colliander 	if (skb) {
133926ad340eSHenning Colliander 		cf->can_id |= CAN_ERR_BUSERROR;
1340ec681b91SJimmy Assarsson 		kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp);
134126ad340eSHenning Colliander 		netif_rx(skb);
134226ad340eSHenning Colliander 	} else {
1343f4845741SJimmy Assarsson 		can->can.dev->stats.rx_dropped++;
134426ad340eSHenning Colliander 		netdev_warn(can->can.dev, "No memory left for err_skb\n");
134526ad340eSHenning Colliander 	}
134626ad340eSHenning Colliander }
134726ad340eSHenning Colliander 
134826ad340eSHenning Colliander static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie,
134926ad340eSHenning Colliander 					   struct kvaser_pciefd_rx_packet *p)
135026ad340eSHenning Colliander {
135126ad340eSHenning Colliander 	struct kvaser_pciefd_can *can;
135226ad340eSHenning Colliander 	bool one_shot_fail = false;
1353954fb212SJimmy Assarsson 	u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
135426ad340eSHenning Colliander 
135526ad340eSHenning Colliander 	if (ch_id >= pcie->nr_channels)
135626ad340eSHenning Colliander 		return -EIO;
135726ad340eSHenning Colliander 
135826ad340eSHenning Colliander 	can = pcie->can[ch_id];
135926ad340eSHenning Colliander 	/* Ignore control packet ACK */
136026ad340eSHenning Colliander 	if (p->header[0] & KVASER_PCIEFD_APACKET_CT)
136126ad340eSHenning Colliander 		return 0;
136226ad340eSHenning Colliander 
136326ad340eSHenning Colliander 	if (p->header[0] & KVASER_PCIEFD_APACKET_NACK) {
136426ad340eSHenning Colliander 		kvaser_pciefd_handle_nack_packet(can, p);
136526ad340eSHenning Colliander 		one_shot_fail = true;
136626ad340eSHenning Colliander 	}
136726ad340eSHenning Colliander 
136826ad340eSHenning Colliander 	if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) {
136926ad340eSHenning Colliander 		netdev_dbg(can->can.dev, "Packet was flushed\n");
137026ad340eSHenning Colliander 	} else {
1371954fb212SJimmy Assarsson 		int echo_idx = FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[0]);
1372f4845741SJimmy Assarsson 		int len;
1373ec681b91SJimmy Assarsson 		u8 count;
1374ec681b91SJimmy Assarsson 		struct sk_buff *skb;
1375ec681b91SJimmy Assarsson 
1376ec681b91SJimmy Assarsson 		skb = can->can.echo_skb[echo_idx];
1377ec681b91SJimmy Assarsson 		if (skb)
1378ec681b91SJimmy Assarsson 			kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp);
1379f4845741SJimmy Assarsson 		len = can_get_echo_skb(can->can.dev, echo_idx, NULL);
1380954fb212SJimmy Assarsson 		count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK,
1381f4845741SJimmy Assarsson 				  ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
138226ad340eSHenning Colliander 
13836fdcd64eSJimmy Assarsson 		if (count < can->can.echo_skb_max && netif_queue_stopped(can->can.dev))
138426ad340eSHenning Colliander 			netif_wake_queue(can->can.dev);
138526ad340eSHenning Colliander 
138626ad340eSHenning Colliander 		if (!one_shot_fail) {
1387f4845741SJimmy Assarsson 			can->can.dev->stats.tx_bytes += len;
1388f4845741SJimmy Assarsson 			can->can.dev->stats.tx_packets++;
138926ad340eSHenning Colliander 		}
139026ad340eSHenning Colliander 	}
139126ad340eSHenning Colliander 
139226ad340eSHenning Colliander 	return 0;
139326ad340eSHenning Colliander }
139426ad340eSHenning Colliander 
139526ad340eSHenning Colliander static int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie,
139626ad340eSHenning Colliander 					      struct kvaser_pciefd_rx_packet *p)
139726ad340eSHenning Colliander {
139826ad340eSHenning Colliander 	struct kvaser_pciefd_can *can;
1399954fb212SJimmy Assarsson 	u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]);
140026ad340eSHenning Colliander 
140126ad340eSHenning Colliander 	if (ch_id >= pcie->nr_channels)
140226ad340eSHenning Colliander 		return -EIO;
140326ad340eSHenning Colliander 
140426ad340eSHenning Colliander 	can = pcie->can[ch_id];
140526ad340eSHenning Colliander 
140626ad340eSHenning Colliander 	if (!completion_done(&can->flush_comp))
140726ad340eSHenning Colliander 		complete(&can->flush_comp);
140826ad340eSHenning Colliander 
140926ad340eSHenning Colliander 	return 0;
141026ad340eSHenning Colliander }
141126ad340eSHenning Colliander 
141226ad340eSHenning Colliander static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
141326ad340eSHenning Colliander 				     int dma_buf)
141426ad340eSHenning Colliander {
141526ad340eSHenning Colliander 	__le32 *buffer = pcie->dma_data[dma_buf];
141626ad340eSHenning Colliander 	__le64 timestamp;
141726ad340eSHenning Colliander 	struct kvaser_pciefd_rx_packet packet;
141826ad340eSHenning Colliander 	struct kvaser_pciefd_rx_packet *p = &packet;
141926ad340eSHenning Colliander 	u8 type;
142026ad340eSHenning Colliander 	int pos = *start_pos;
142126ad340eSHenning Colliander 	int size;
142226ad340eSHenning Colliander 	int ret = 0;
142326ad340eSHenning Colliander 
142426ad340eSHenning Colliander 	size = le32_to_cpu(buffer[pos++]);
142526ad340eSHenning Colliander 	if (!size) {
142626ad340eSHenning Colliander 		*start_pos = 0;
142726ad340eSHenning Colliander 		return 0;
142826ad340eSHenning Colliander 	}
142926ad340eSHenning Colliander 
143026ad340eSHenning Colliander 	p->header[0] = le32_to_cpu(buffer[pos++]);
143126ad340eSHenning Colliander 	p->header[1] = le32_to_cpu(buffer[pos++]);
143226ad340eSHenning Colliander 
143326ad340eSHenning Colliander 	/* Read 64-bit timestamp */
143426ad340eSHenning Colliander 	memcpy(&timestamp, &buffer[pos], sizeof(__le64));
143526ad340eSHenning Colliander 	pos += 2;
143626ad340eSHenning Colliander 	p->timestamp = le64_to_cpu(timestamp);
143726ad340eSHenning Colliander 
1438954fb212SJimmy Assarsson 	type = FIELD_GET(KVASER_PCIEFD_PACKET_TYPE_MASK, p->header[1]);
143926ad340eSHenning Colliander 	switch (type) {
144026ad340eSHenning Colliander 	case KVASER_PCIEFD_PACK_TYPE_DATA:
144126ad340eSHenning Colliander 		ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]);
144226ad340eSHenning Colliander 		if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) {
144326ad340eSHenning Colliander 			u8 data_len;
144426ad340eSHenning Colliander 
1445954fb212SJimmy Assarsson 			data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK,
1446954fb212SJimmy Assarsson 							    p->header[1]));
144726ad340eSHenning Colliander 			pos += DIV_ROUND_UP(data_len, 4);
144826ad340eSHenning Colliander 		}
144926ad340eSHenning Colliander 		break;
145026ad340eSHenning Colliander 
145126ad340eSHenning Colliander 	case KVASER_PCIEFD_PACK_TYPE_ACK:
145226ad340eSHenning Colliander 		ret = kvaser_pciefd_handle_ack_packet(pcie, p);
145326ad340eSHenning Colliander 		break;
145426ad340eSHenning Colliander 
145526ad340eSHenning Colliander 	case KVASER_PCIEFD_PACK_TYPE_STATUS:
145626ad340eSHenning Colliander 		ret = kvaser_pciefd_handle_status_packet(pcie, p);
145726ad340eSHenning Colliander 		break;
145826ad340eSHenning Colliander 
145926ad340eSHenning Colliander 	case KVASER_PCIEFD_PACK_TYPE_ERROR:
146026ad340eSHenning Colliander 		ret = kvaser_pciefd_handle_error_packet(pcie, p);
146126ad340eSHenning Colliander 		break;
146226ad340eSHenning Colliander 
146326ad340eSHenning Colliander 	case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK:
146426ad340eSHenning Colliander 		ret = kvaser_pciefd_handle_eflush_packet(pcie, p);
146526ad340eSHenning Colliander 		break;
146626ad340eSHenning Colliander 
146726ad340eSHenning Colliander 	case KVASER_PCIEFD_PACK_TYPE_ACK_DATA:
146826ad340eSHenning Colliander 	case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD:
146976c66ddfSJimmy Assarsson 	case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK:
147026ad340eSHenning Colliander 	case KVASER_PCIEFD_PACK_TYPE_TXRQ:
147126ad340eSHenning Colliander 		dev_info(&pcie->pci->dev,
147226ad340eSHenning Colliander 			 "Received unexpected packet type 0x%08X\n", type);
147326ad340eSHenning Colliander 		break;
147426ad340eSHenning Colliander 
147526ad340eSHenning Colliander 	default:
147626ad340eSHenning Colliander 		dev_err(&pcie->pci->dev, "Unknown packet type 0x%08X\n", type);
147726ad340eSHenning Colliander 		ret = -EIO;
147826ad340eSHenning Colliander 		break;
147926ad340eSHenning Colliander 	}
148026ad340eSHenning Colliander 
148126ad340eSHenning Colliander 	if (ret)
148226ad340eSHenning Colliander 		return ret;
148326ad340eSHenning Colliander 
148426ad340eSHenning Colliander 	/* Position does not point to the end of the package,
148526ad340eSHenning Colliander 	 * corrupted packet size?
148626ad340eSHenning Colliander 	 */
148726ad340eSHenning Colliander 	if ((*start_pos + size) != pos)
148826ad340eSHenning Colliander 		return -EIO;
148926ad340eSHenning Colliander 
149026ad340eSHenning Colliander 	/* Point to the next packet header, if any */
149126ad340eSHenning Colliander 	*start_pos = pos;
149226ad340eSHenning Colliander 
149326ad340eSHenning Colliander 	return ret;
149426ad340eSHenning Colliander }
149526ad340eSHenning Colliander 
149626ad340eSHenning Colliander static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf)
149726ad340eSHenning Colliander {
149826ad340eSHenning Colliander 	int pos = 0;
149926ad340eSHenning Colliander 	int res = 0;
150026ad340eSHenning Colliander 
150126ad340eSHenning Colliander 	do {
150226ad340eSHenning Colliander 		res = kvaser_pciefd_read_packet(pcie, &pos, dma_buf);
150326ad340eSHenning Colliander 	} while (!res && pos > 0 && pos < KVASER_PCIEFD_DMA_SIZE);
150426ad340eSHenning Colliander 
150526ad340eSHenning Colliander 	return res;
150626ad340eSHenning Colliander }
150726ad340eSHenning Colliander 
150824aecf55SJimmy Assarsson static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
150926ad340eSHenning Colliander {
1510*c2ad8129SJimmy Assarsson 	u32 irq = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
151126ad340eSHenning Colliander 
151226ad340eSHenning Colliander 	if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) {
151326ad340eSHenning Colliander 		kvaser_pciefd_read_buffer(pcie, 0);
151426ad340eSHenning Colliander 		/* Reset DMA buffer 0 */
151526ad340eSHenning Colliander 		iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
1516*c2ad8129SJimmy Assarsson 			  KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
151726ad340eSHenning Colliander 	}
151826ad340eSHenning Colliander 
151926ad340eSHenning Colliander 	if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) {
152026ad340eSHenning Colliander 		kvaser_pciefd_read_buffer(pcie, 1);
152126ad340eSHenning Colliander 		/* Reset DMA buffer 1 */
152226ad340eSHenning Colliander 		iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
1523*c2ad8129SJimmy Assarsson 			  KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
152426ad340eSHenning Colliander 	}
152526ad340eSHenning Colliander 
152626ad340eSHenning Colliander 	if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 ||
152726ad340eSHenning Colliander 	    irq & KVASER_PCIEFD_SRB_IRQ_DOF1 ||
152826ad340eSHenning Colliander 	    irq & KVASER_PCIEFD_SRB_IRQ_DUF0 ||
152926ad340eSHenning Colliander 	    irq & KVASER_PCIEFD_SRB_IRQ_DUF1)
153026ad340eSHenning Colliander 		dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq);
153126ad340eSHenning Colliander 
1532*c2ad8129SJimmy Assarsson 	iowrite32(irq, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
153326ad340eSHenning Colliander }
153426ad340eSHenning Colliander 
153524aecf55SJimmy Assarsson static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
153626ad340eSHenning Colliander {
153726ad340eSHenning Colliander 	u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
153826ad340eSHenning Colliander 
153926ad340eSHenning Colliander 	if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF)
154026ad340eSHenning Colliander 		netdev_err(can->can.dev, "Tx FIFO overflow\n");
154126ad340eSHenning Colliander 
154226ad340eSHenning Colliander 	if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP)
154326ad340eSHenning Colliander 		netdev_err(can->can.dev,
154426ad340eSHenning Colliander 			   "Fail to change bittiming, when not in reset mode\n");
154526ad340eSHenning Colliander 
154626ad340eSHenning Colliander 	if (irq & KVASER_PCIEFD_KCAN_IRQ_FDIC)
154726ad340eSHenning Colliander 		netdev_err(can->can.dev, "CAN FD frame in CAN mode\n");
154826ad340eSHenning Colliander 
154926ad340eSHenning Colliander 	if (irq & KVASER_PCIEFD_KCAN_IRQ_ROF)
155026ad340eSHenning Colliander 		netdev_err(can->can.dev, "Rx FIFO overflow\n");
155126ad340eSHenning Colliander 
155226ad340eSHenning Colliander 	iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
155326ad340eSHenning Colliander }
155426ad340eSHenning Colliander 
155526ad340eSHenning Colliander static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
155626ad340eSHenning Colliander {
155726ad340eSHenning Colliander 	struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev;
1558*c2ad8129SJimmy Assarsson 	const struct kvaser_pciefd_irq_mask *irq_mask = pcie->driver_data->irq_mask;
1559*c2ad8129SJimmy Assarsson 	u32 board_irq = ioread32(KVASER_PCIEFD_PCI_IRQ_ADDR(pcie));
156026ad340eSHenning Colliander 	int i;
156126ad340eSHenning Colliander 
1562*c2ad8129SJimmy Assarsson 	if (!(board_irq & irq_mask->all))
156326ad340eSHenning Colliander 		return IRQ_NONE;
156426ad340eSHenning Colliander 
1565*c2ad8129SJimmy Assarsson 	if (board_irq & irq_mask->kcan_rx0)
156626ad340eSHenning Colliander 		kvaser_pciefd_receive_irq(pcie);
156726ad340eSHenning Colliander 
156826ad340eSHenning Colliander 	for (i = 0; i < pcie->nr_channels; i++) {
156926ad340eSHenning Colliander 		if (!pcie->can[i]) {
157026ad340eSHenning Colliander 			dev_err(&pcie->pci->dev,
157126ad340eSHenning Colliander 				"IRQ mask points to unallocated controller\n");
157226ad340eSHenning Colliander 			break;
157326ad340eSHenning Colliander 		}
157426ad340eSHenning Colliander 
157526ad340eSHenning Colliander 		/* Check that mask matches channel (i) IRQ mask */
1576*c2ad8129SJimmy Assarsson 		if (board_irq & irq_mask->kcan_tx[i])
157726ad340eSHenning Colliander 			kvaser_pciefd_transmit_irq(pcie->can[i]);
157826ad340eSHenning Colliander 	}
157926ad340eSHenning Colliander 
158026ad340eSHenning Colliander 	return IRQ_HANDLED;
158126ad340eSHenning Colliander }
158226ad340eSHenning Colliander 
158326ad340eSHenning Colliander static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)
158426ad340eSHenning Colliander {
158526ad340eSHenning Colliander 	int i;
158626ad340eSHenning Colliander 
158726ad340eSHenning Colliander 	for (i = 0; i < pcie->nr_channels; i++) {
1588f4845741SJimmy Assarsson 		struct kvaser_pciefd_can *can = pcie->can[i];
1589f4845741SJimmy Assarsson 
159026ad340eSHenning Colliander 		if (can) {
1591f4845741SJimmy Assarsson 			iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
159226ad340eSHenning Colliander 			kvaser_pciefd_pwm_stop(can);
159326ad340eSHenning Colliander 			free_candev(can->can.dev);
159426ad340eSHenning Colliander 		}
159526ad340eSHenning Colliander 	}
159626ad340eSHenning Colliander }
159726ad340eSHenning Colliander 
159826ad340eSHenning Colliander static int kvaser_pciefd_probe(struct pci_dev *pdev,
159926ad340eSHenning Colliander 			       const struct pci_device_id *id)
160026ad340eSHenning Colliander {
160126ad340eSHenning Colliander 	int err;
160226ad340eSHenning Colliander 	struct kvaser_pciefd *pcie;
1603*c2ad8129SJimmy Assarsson 	const struct kvaser_pciefd_irq_mask *irq_mask;
1604*c2ad8129SJimmy Assarsson 	void __iomem *irq_en_base;
160526ad340eSHenning Colliander 
160626ad340eSHenning Colliander 	pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
160726ad340eSHenning Colliander 	if (!pcie)
160826ad340eSHenning Colliander 		return -ENOMEM;
160926ad340eSHenning Colliander 
161026ad340eSHenning Colliander 	pci_set_drvdata(pdev, pcie);
161126ad340eSHenning Colliander 	pcie->pci = pdev;
1612*c2ad8129SJimmy Assarsson 	pcie->driver_data = (const struct kvaser_pciefd_driver_data *)id->driver_data;
1613*c2ad8129SJimmy Assarsson 	irq_mask = pcie->driver_data->irq_mask;
161426ad340eSHenning Colliander 
161526ad340eSHenning Colliander 	err = pci_enable_device(pdev);
161626ad340eSHenning Colliander 	if (err)
161726ad340eSHenning Colliander 		return err;
161826ad340eSHenning Colliander 
161926ad340eSHenning Colliander 	err = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME);
162026ad340eSHenning Colliander 	if (err)
162126ad340eSHenning Colliander 		goto err_disable_pci;
162226ad340eSHenning Colliander 
162326ad340eSHenning Colliander 	pcie->reg_base = pci_iomap(pdev, 0, 0);
162426ad340eSHenning Colliander 	if (!pcie->reg_base) {
162526ad340eSHenning Colliander 		err = -ENOMEM;
162626ad340eSHenning Colliander 		goto err_release_regions;
162726ad340eSHenning Colliander 	}
162826ad340eSHenning Colliander 
162926ad340eSHenning Colliander 	err = kvaser_pciefd_setup_board(pcie);
163026ad340eSHenning Colliander 	if (err)
163126ad340eSHenning Colliander 		goto err_pci_iounmap;
163226ad340eSHenning Colliander 
163326ad340eSHenning Colliander 	err = kvaser_pciefd_setup_dma(pcie);
163426ad340eSHenning Colliander 	if (err)
163526ad340eSHenning Colliander 		goto err_pci_iounmap;
163626ad340eSHenning Colliander 
163726ad340eSHenning Colliander 	pci_set_master(pdev);
163826ad340eSHenning Colliander 
163926ad340eSHenning Colliander 	err = kvaser_pciefd_setup_can_ctrls(pcie);
164026ad340eSHenning Colliander 	if (err)
164126ad340eSHenning Colliander 		goto err_teardown_can_ctrls;
164226ad340eSHenning Colliander 
164384762d8dSJimmy Assarsson 	err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
164484762d8dSJimmy Assarsson 			  IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
164584762d8dSJimmy Assarsson 	if (err)
164684762d8dSJimmy Assarsson 		goto err_teardown_can_ctrls;
164784762d8dSJimmy Assarsson 
164826ad340eSHenning Colliander 	iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1,
1649*c2ad8129SJimmy Assarsson 		  KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
165026ad340eSHenning Colliander 
165126ad340eSHenning Colliander 	iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 |
165226ad340eSHenning Colliander 		  KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 |
165326ad340eSHenning Colliander 		  KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1,
1654*c2ad8129SJimmy Assarsson 		  KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IEN_REG);
165526ad340eSHenning Colliander 
16567c921556SJimmy Assarsson 	/* Enable PCI interrupts */
1657*c2ad8129SJimmy Assarsson 	irq_en_base = KVASER_PCIEFD_PCI_IEN_ADDR(pcie);
1658*c2ad8129SJimmy Assarsson 	iowrite32(irq_mask->all, irq_en_base);
165926ad340eSHenning Colliander 	/* Ready the DMA buffers */
166026ad340eSHenning Colliander 	iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
1661*c2ad8129SJimmy Assarsson 		  KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
166226ad340eSHenning Colliander 	iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
1663*c2ad8129SJimmy Assarsson 		  KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
166426ad340eSHenning Colliander 
166526ad340eSHenning Colliander 	err = kvaser_pciefd_reg_candev(pcie);
166626ad340eSHenning Colliander 	if (err)
166726ad340eSHenning Colliander 		goto err_free_irq;
166826ad340eSHenning Colliander 
166926ad340eSHenning Colliander 	return 0;
167026ad340eSHenning Colliander 
167126ad340eSHenning Colliander err_free_irq:
167211164bc3SJimmy Assarsson 	/* Disable PCI interrupts */
1673*c2ad8129SJimmy Assarsson 	iowrite32(0, irq_en_base);
167426ad340eSHenning Colliander 	free_irq(pcie->pci->irq, pcie);
167526ad340eSHenning Colliander 
167626ad340eSHenning Colliander err_teardown_can_ctrls:
167726ad340eSHenning Colliander 	kvaser_pciefd_teardown_can_ctrls(pcie);
1678*c2ad8129SJimmy Assarsson 	iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
167926ad340eSHenning Colliander 	pci_clear_master(pdev);
168026ad340eSHenning Colliander 
168126ad340eSHenning Colliander err_pci_iounmap:
168226ad340eSHenning Colliander 	pci_iounmap(pdev, pcie->reg_base);
168326ad340eSHenning Colliander 
168426ad340eSHenning Colliander err_release_regions:
168526ad340eSHenning Colliander 	pci_release_regions(pdev);
168626ad340eSHenning Colliander 
168726ad340eSHenning Colliander err_disable_pci:
168826ad340eSHenning Colliander 	pci_disable_device(pdev);
168926ad340eSHenning Colliander 
169026ad340eSHenning Colliander 	return err;
169126ad340eSHenning Colliander }
169226ad340eSHenning Colliander 
169326ad340eSHenning Colliander static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie)
169426ad340eSHenning Colliander {
169526ad340eSHenning Colliander 	int i;
169626ad340eSHenning Colliander 
169726ad340eSHenning Colliander 	for (i = 0; i < pcie->nr_channels; i++) {
1698f4845741SJimmy Assarsson 		struct kvaser_pciefd_can *can = pcie->can[i];
1699f4845741SJimmy Assarsson 
170026ad340eSHenning Colliander 		if (can) {
1701f4845741SJimmy Assarsson 			iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
170226ad340eSHenning Colliander 			unregister_candev(can->can.dev);
170326ad340eSHenning Colliander 			del_timer(&can->bec_poll_timer);
170426ad340eSHenning Colliander 			kvaser_pciefd_pwm_stop(can);
170526ad340eSHenning Colliander 			free_candev(can->can.dev);
170626ad340eSHenning Colliander 		}
170726ad340eSHenning Colliander 	}
170826ad340eSHenning Colliander }
170926ad340eSHenning Colliander 
171026ad340eSHenning Colliander static void kvaser_pciefd_remove(struct pci_dev *pdev)
171126ad340eSHenning Colliander {
171226ad340eSHenning Colliander 	struct kvaser_pciefd *pcie = pci_get_drvdata(pdev);
171326ad340eSHenning Colliander 
171426ad340eSHenning Colliander 	kvaser_pciefd_remove_all_ctrls(pcie);
171526ad340eSHenning Colliander 
17167c921556SJimmy Assarsson 	/* Disable interrupts */
1717*c2ad8129SJimmy Assarsson 	iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
1718*c2ad8129SJimmy Assarsson 	iowrite32(0, KVASER_PCIEFD_PCI_IEN_ADDR(pcie));
171926ad340eSHenning Colliander 
172026ad340eSHenning Colliander 	free_irq(pcie->pci->irq, pcie);
172126ad340eSHenning Colliander 
172226ad340eSHenning Colliander 	pci_iounmap(pdev, pcie->reg_base);
172326ad340eSHenning Colliander 	pci_release_regions(pdev);
172426ad340eSHenning Colliander 	pci_disable_device(pdev);
172526ad340eSHenning Colliander }
172626ad340eSHenning Colliander 
172726ad340eSHenning Colliander static struct pci_driver kvaser_pciefd = {
172826ad340eSHenning Colliander 	.name = KVASER_PCIEFD_DRV_NAME,
172926ad340eSHenning Colliander 	.id_table = kvaser_pciefd_id_table,
173026ad340eSHenning Colliander 	.probe = kvaser_pciefd_probe,
173126ad340eSHenning Colliander 	.remove = kvaser_pciefd_remove,
173226ad340eSHenning Colliander };
173326ad340eSHenning Colliander 
173426ad340eSHenning Colliander module_pci_driver(kvaser_pciefd)
1735