18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
28c2ecf20Sopenharmony_ci/* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved.
38c2ecf20Sopenharmony_ci * Parts of this driver are based on the following:
48c2ecf20Sopenharmony_ci *  - Kvaser linux pciefd driver (version 5.25)
58c2ecf20Sopenharmony_ci *  - PEAK linux canfd driver
68c2ecf20Sopenharmony_ci *  - Altera Avalon EPCS flash controller driver
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/device.h>
128c2ecf20Sopenharmony_ci#include <linux/pci.h>
138c2ecf20Sopenharmony_ci#include <linux/can/dev.h>
148c2ecf20Sopenharmony_ci#include <linux/timer.h>
158c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
168c2ecf20Sopenharmony_ci#include <linux/crc32.h>
178c2ecf20Sopenharmony_ci#include <linux/iopoll.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
208c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kvaser AB <support@kvaser.com>");
218c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_DRV_NAME "kvaser_pciefd"
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000)
268c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200))
278c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_MAX_ERR_REP 256
288c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17
298c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4
308c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_DMA_COUNT 2
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_DMA_SIZE (4 * 1024)
338c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0)
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_VENDOR 0x1a07
368c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_4HS_ID 0x0d
378c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_2HS_ID 0x0e
388c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_HS_ID 0x0f
398c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_MINIPCIE_HS_ID 0x10
408c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_MINIPCIE_2HS_ID 0x11
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* PCIe IRQ registers */
438c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_IRQ_REG 0x40
448c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_IEN_REG 0x50
458c2ecf20Sopenharmony_ci/* DMA map */
468c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_DMA_MAP_BASE 0x1000
478c2ecf20Sopenharmony_ci/* Kvaser KCAN CAN controller registers */
488c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN0_BASE 0x10000
498c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000
508c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
518c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
528c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0
538c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CMD_REG 0x400
548c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IEN_REG 0x408
558c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410
568c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_TX_NPACKETS_REG 0x414
578c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_REG 0x418
588c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
598c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
608c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
618c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
628c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_PWM_REG 0x430
638c2ecf20Sopenharmony_ci/* Loopback control register */
648c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_LOOP_REG 0x1f000
658c2ecf20Sopenharmony_ci/* System identification and information registers */
668c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_BASE 0x1f020
678c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_VERSION_REG (KVASER_PCIEFD_SYSID_BASE + 0x8)
688c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_CANFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0xc)
698c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_BUSFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0x10)
708c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_BUILD_REG (KVASER_PCIEFD_SYSID_BASE + 0x14)
718c2ecf20Sopenharmony_ci/* Shared receive buffer registers */
728c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_BASE 0x1f200
738c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_FIFO_LAST_REG (KVASER_PCIEFD_SRB_BASE + 0x1f4)
748c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CMD_REG (KVASER_PCIEFD_SRB_BASE + 0x200)
758c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IEN_REG (KVASER_PCIEFD_SRB_BASE + 0x204)
768c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_REG (KVASER_PCIEFD_SRB_BASE + 0x20c)
778c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210)
788c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214)
798c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218)
808c2ecf20Sopenharmony_ci/* EPCS flash controller registers */
818c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_BASE 0x1fc00
828c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_RX_REG KVASER_PCIEFD_SPI_BASE
838c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_TX_REG (KVASER_PCIEFD_SPI_BASE + 0x4)
848c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_STATUS_REG (KVASER_PCIEFD_SPI_BASE + 0x8)
858c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_CTRL_REG (KVASER_PCIEFD_SPI_BASE + 0xc)
868c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_SSEL_REG (KVASER_PCIEFD_SPI_BASE + 0x14)
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_IRQ_ALL_MSK 0x1f
898c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_IRQ_SRB BIT(4)
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_NRCHAN_SHIFT 24
928c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT 16
938c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT 1
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/* Reset DMA buffer 0, 1 and FIFO offset */
968c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4)
978c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5)
988c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CMD_FOR BIT(0)
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/* DMA packet done, buffer 0 and 1 */
1018c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8)
1028c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9)
1038c2ecf20Sopenharmony_ci/* DMA overflow, buffer 0 and 1 */
1048c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10)
1058c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11)
1068c2ecf20Sopenharmony_ci/* DMA underflow, buffer 0 and 1 */
1078c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12)
1088c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13)
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/* DMA idle */
1118c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_STAT_DI BIT(15)
1128c2ecf20Sopenharmony_ci/* DMA support */
1138c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/* SRB current packet level */
1168c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/* DMA Enable */
1198c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0)
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci/* EPCS flash controller definitions */
1228c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_IMG_SZ (64 * 1024)
1238c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_IMG_OFFSET (31 * 65536L)
1248c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_MAX_PARAMS 256
1258c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_MAGIC 0xcafef00d
1268c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_PARAM_MAX_SZ 24
1278c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_SYS_VER 1
1288c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_PARAM_NR_CHAN 130
1298c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_TMT BIT(5)
1308c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_TRDY BIT(6)
1318c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_RRDY BIT(7)
1328c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_FLASH_ID_EPCS16 0x14
1338c2ecf20Sopenharmony_ci/* Commands for controlling the onboard flash */
1348c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_FLASH_RES_CMD 0xab
1358c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_FLASH_READ_CMD 0x3
1368c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_FLASH_STATUS_CMD 0x5
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci/* Kvaser KCAN definitions */
1398c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CTRL_EFLUSH (4 << 29)
1408c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CTRL_EFRAME (5 << 29)
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT 16
1438c2ecf20Sopenharmony_ci/* Request status packet */
1448c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0)
1458c2ecf20Sopenharmony_ci/* Abort, flush and reset */
1468c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CMD_AT BIT(1)
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/* Tx FIFO unaligned read */
1498c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0)
1508c2ecf20Sopenharmony_ci/* Tx FIFO unaligned end */
1518c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1)
1528c2ecf20Sopenharmony_ci/* Bus parameter protection error */
1538c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2)
1548c2ecf20Sopenharmony_ci/* FDF bit when controller is in classic mode */
1558c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3)
1568c2ecf20Sopenharmony_ci/* Rx FIFO overflow */
1578c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5)
1588c2ecf20Sopenharmony_ci/* Abort done */
1598c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13)
1608c2ecf20Sopenharmony_ci/* Tx buffer flush done */
1618c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14)
1628c2ecf20Sopenharmony_ci/* Tx FIFO overflow */
1638c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15)
1648c2ecf20Sopenharmony_ci/* Tx FIFO empty */
1658c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16)
1668c2ecf20Sopenharmony_ci/* Transmitter unaligned */
1678c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17)
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT 16
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT 24
1728c2ecf20Sopenharmony_ci/* Abort request */
1738c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7)
1748c2ecf20Sopenharmony_ci/* Idle state. Controller in reset mode and no abort or flush pending */
1758c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10)
1768c2ecf20Sopenharmony_ci/* Bus off */
1778c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11)
1788c2ecf20Sopenharmony_ci/* Reset mode request */
1798c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14)
1808c2ecf20Sopenharmony_ci/* Controller in reset mode */
1818c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15)
1828c2ecf20Sopenharmony_ci/* Controller got one-shot capability */
1838c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16)
1848c2ecf20Sopenharmony_ci/* Controller got CAN FD capability */
1858c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_FD BIT(19)
1868c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK (KVASER_PCIEFD_KCAN_STAT_AR | \
1878c2ecf20Sopenharmony_ci	KVASER_PCIEFD_KCAN_STAT_BOFF | KVASER_PCIEFD_KCAN_STAT_RMR | \
1888c2ecf20Sopenharmony_ci	KVASER_PCIEFD_KCAN_STAT_IRM)
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci/* Reset mode */
1918c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8)
1928c2ecf20Sopenharmony_ci/* Listen only mode */
1938c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9)
1948c2ecf20Sopenharmony_ci/* Error packet enable */
1958c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12)
1968c2ecf20Sopenharmony_ci/* CAN FD non-ISO */
1978c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15)
1988c2ecf20Sopenharmony_ci/* Acknowledgment packet type */
1998c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20)
2008c2ecf20Sopenharmony_ci/* Active error flag enable. Clear to force error passive */
2018c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23)
2028c2ecf20Sopenharmony_ci/* Classic CAN mode */
2038c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31)
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT 13
2068c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT 17
2078c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT 26
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT 16
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci/* Kvaser KCAN packet types */
2128c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_DATA 0
2138c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_ACK 1
2148c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_TXRQ 2
2158c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_ERROR 3
2168c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 4
2178c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 5
2188c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 6
2198c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_STATUS 8
2208c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 9
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci/* Kvaser KCAN packet common definitions */
2238c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACKET_SEQ_MSK 0xff
2248c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACKET_CHID_SHIFT 25
2258c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACKET_TYPE_SHIFT 28
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci/* Kvaser KCAN TDATA and RDATA first word */
2288c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_IDE BIT(30)
2298c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_RTR BIT(29)
2308c2ecf20Sopenharmony_ci/* Kvaser KCAN TDATA and RDATA second word */
2318c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_ESI BIT(13)
2328c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_BRS BIT(14)
2338c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_FDF BIT(15)
2348c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_DLC_SHIFT 8
2358c2ecf20Sopenharmony_ci/* Kvaser KCAN TDATA second word */
2368c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_TPACKET_SMS BIT(16)
2378c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_TPACKET_AREQ BIT(31)
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci/* Kvaser KCAN APACKET */
2408c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_APACKET_FLU BIT(8)
2418c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_APACKET_CT BIT(9)
2428c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_APACKET_ABL BIT(10)
2438c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_APACKET_NACK BIT(11)
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci/* Kvaser KCAN SPACK first word */
2468c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_RXERR_SHIFT 8
2478c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_BOFF BIT(16)
2488c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_IDET BIT(20)
2498c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_IRM BIT(21)
2508c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_RMCD BIT(22)
2518c2ecf20Sopenharmony_ci/* Kvaser KCAN SPACK second word */
2528c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_AUTO BIT(21)
2538c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_EWLR BIT(23)
2548c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_EPLR BIT(24)
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci/* Kvaser KCAN_EPACK second word */
2578c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0)
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_cistruct kvaser_pciefd;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cistruct kvaser_pciefd_can {
2628c2ecf20Sopenharmony_ci	struct can_priv can;
2638c2ecf20Sopenharmony_ci	struct kvaser_pciefd *kv_pcie;
2648c2ecf20Sopenharmony_ci	void __iomem *reg_base;
2658c2ecf20Sopenharmony_ci	struct can_berr_counter bec;
2668c2ecf20Sopenharmony_ci	u8 cmd_seq;
2678c2ecf20Sopenharmony_ci	int err_rep_cnt;
2688c2ecf20Sopenharmony_ci	int echo_idx;
2698c2ecf20Sopenharmony_ci	spinlock_t lock; /* Locks sensitive registers (e.g. MODE) */
2708c2ecf20Sopenharmony_ci	spinlock_t echo_lock; /* Locks the message echo buffer */
2718c2ecf20Sopenharmony_ci	struct timer_list bec_poll_timer;
2728c2ecf20Sopenharmony_ci	struct completion start_comp, flush_comp;
2738c2ecf20Sopenharmony_ci};
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistruct kvaser_pciefd {
2768c2ecf20Sopenharmony_ci	struct pci_dev *pci;
2778c2ecf20Sopenharmony_ci	void __iomem *reg_base;
2788c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS];
2798c2ecf20Sopenharmony_ci	void *dma_data[KVASER_PCIEFD_DMA_COUNT];
2808c2ecf20Sopenharmony_ci	u8 nr_channels;
2818c2ecf20Sopenharmony_ci	u32 bus_freq;
2828c2ecf20Sopenharmony_ci	u32 freq;
2838c2ecf20Sopenharmony_ci	u32 freq_to_ticks_div;
2848c2ecf20Sopenharmony_ci};
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_cistruct kvaser_pciefd_rx_packet {
2878c2ecf20Sopenharmony_ci	u32 header[2];
2888c2ecf20Sopenharmony_ci	u64 timestamp;
2898c2ecf20Sopenharmony_ci};
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistruct kvaser_pciefd_tx_packet {
2928c2ecf20Sopenharmony_ci	u32 header[2];
2938c2ecf20Sopenharmony_ci	u8 data[64];
2948c2ecf20Sopenharmony_ci};
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic const struct can_bittiming_const kvaser_pciefd_bittiming_const = {
2978c2ecf20Sopenharmony_ci	.name = KVASER_PCIEFD_DRV_NAME,
2988c2ecf20Sopenharmony_ci	.tseg1_min = 1,
2998c2ecf20Sopenharmony_ci	.tseg1_max = 512,
3008c2ecf20Sopenharmony_ci	.tseg2_min = 1,
3018c2ecf20Sopenharmony_ci	.tseg2_max = 32,
3028c2ecf20Sopenharmony_ci	.sjw_max = 16,
3038c2ecf20Sopenharmony_ci	.brp_min = 1,
3048c2ecf20Sopenharmony_ci	.brp_max = 8192,
3058c2ecf20Sopenharmony_ci	.brp_inc = 1,
3068c2ecf20Sopenharmony_ci};
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_cistruct kvaser_pciefd_cfg_param {
3098c2ecf20Sopenharmony_ci	__le32 magic;
3108c2ecf20Sopenharmony_ci	__le32 nr;
3118c2ecf20Sopenharmony_ci	__le32 len;
3128c2ecf20Sopenharmony_ci	u8 data[KVASER_PCIEFD_CFG_PARAM_MAX_SZ];
3138c2ecf20Sopenharmony_ci};
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistruct kvaser_pciefd_cfg_img {
3168c2ecf20Sopenharmony_ci	__le32 version;
3178c2ecf20Sopenharmony_ci	__le32 magic;
3188c2ecf20Sopenharmony_ci	__le32 crc;
3198c2ecf20Sopenharmony_ci	struct kvaser_pciefd_cfg_param params[KVASER_PCIEFD_CFG_MAX_PARAMS];
3208c2ecf20Sopenharmony_ci};
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic struct pci_device_id kvaser_pciefd_id_table[] = {
3238c2ecf20Sopenharmony_ci	{ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_ID), },
3248c2ecf20Sopenharmony_ci	{ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_ID), },
3258c2ecf20Sopenharmony_ci	{ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_ID), },
3268c2ecf20Sopenharmony_ci	{ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_ID), },
3278c2ecf20Sopenharmony_ci	{ PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_ID), },
3288c2ecf20Sopenharmony_ci	{ 0,},
3298c2ecf20Sopenharmony_ci};
3308c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci/* Onboard flash memory functions */
3338c2ecf20Sopenharmony_cistatic int kvaser_pciefd_spi_wait_loop(struct kvaser_pciefd *pcie, int msk)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	u32 res;
3368c2ecf20Sopenharmony_ci	int ret;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	ret = readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG,
3398c2ecf20Sopenharmony_ci				 res, res & msk, 0, 10);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	return ret;
3428c2ecf20Sopenharmony_ci}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_cistatic int kvaser_pciefd_spi_cmd(struct kvaser_pciefd *pcie, const u8 *tx,
3458c2ecf20Sopenharmony_ci				 u32 tx_len, u8 *rx, u32 rx_len)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	int c;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	iowrite32(BIT(0), pcie->reg_base + KVASER_PCIEFD_SPI_SSEL_REG);
3508c2ecf20Sopenharmony_ci	iowrite32(BIT(10), pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG);
3518c2ecf20Sopenharmony_ci	ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	c = tx_len;
3548c2ecf20Sopenharmony_ci	while (c--) {
3558c2ecf20Sopenharmony_ci		if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY))
3568c2ecf20Sopenharmony_ci			return -EIO;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci		iowrite32(*tx++, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci		if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY))
3618c2ecf20Sopenharmony_ci			return -EIO;
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci		ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
3648c2ecf20Sopenharmony_ci	}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	c = rx_len;
3678c2ecf20Sopenharmony_ci	while (c-- > 0) {
3688c2ecf20Sopenharmony_ci		if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY))
3698c2ecf20Sopenharmony_ci			return -EIO;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci		iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci		if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY))
3748c2ecf20Sopenharmony_ci			return -EIO;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci		*rx++ = ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG);
3778c2ecf20Sopenharmony_ci	}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TMT))
3808c2ecf20Sopenharmony_ci		return -EIO;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	if (c != -1) {
3858c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev, "Flash SPI transfer failed\n");
3868c2ecf20Sopenharmony_ci		return -EIO;
3878c2ecf20Sopenharmony_ci	}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	return 0;
3908c2ecf20Sopenharmony_ci}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic int kvaser_pciefd_cfg_read_and_verify(struct kvaser_pciefd *pcie,
3938c2ecf20Sopenharmony_ci					     struct kvaser_pciefd_cfg_img *img)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	int offset = KVASER_PCIEFD_CFG_IMG_OFFSET;
3968c2ecf20Sopenharmony_ci	int res, crc;
3978c2ecf20Sopenharmony_ci	u8 *crc_buff;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	u8 cmd[] = {
4008c2ecf20Sopenharmony_ci		KVASER_PCIEFD_FLASH_READ_CMD,
4018c2ecf20Sopenharmony_ci		(u8)((offset >> 16) & 0xff),
4028c2ecf20Sopenharmony_ci		(u8)((offset >> 8) & 0xff),
4038c2ecf20Sopenharmony_ci		(u8)(offset & 0xff)
4048c2ecf20Sopenharmony_ci	};
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), (u8 *)img,
4078c2ecf20Sopenharmony_ci				    KVASER_PCIEFD_CFG_IMG_SZ);
4088c2ecf20Sopenharmony_ci	if (res)
4098c2ecf20Sopenharmony_ci		return res;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	crc_buff = (u8 *)img->params;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	if (le32_to_cpu(img->version) != KVASER_PCIEFD_CFG_SYS_VER) {
4148c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev,
4158c2ecf20Sopenharmony_ci			"Config flash corrupted, version number is wrong\n");
4168c2ecf20Sopenharmony_ci		return -ENODEV;
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if (le32_to_cpu(img->magic) != KVASER_PCIEFD_CFG_MAGIC) {
4208c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev,
4218c2ecf20Sopenharmony_ci			"Config flash corrupted, magic number is wrong\n");
4228c2ecf20Sopenharmony_ci		return -ENODEV;
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	crc = ~crc32_be(0xffffffff, crc_buff, sizeof(img->params));
4268c2ecf20Sopenharmony_ci	if (le32_to_cpu(img->crc) != crc) {
4278c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev,
4288c2ecf20Sopenharmony_ci			"Stored CRC does not match flash image contents\n");
4298c2ecf20Sopenharmony_ci		return -EIO;
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	return 0;
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_cistatic void kvaser_pciefd_cfg_read_params(struct kvaser_pciefd *pcie,
4368c2ecf20Sopenharmony_ci					  struct kvaser_pciefd_cfg_img *img)
4378c2ecf20Sopenharmony_ci{
4388c2ecf20Sopenharmony_ci	struct kvaser_pciefd_cfg_param *param;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	param = &img->params[KVASER_PCIEFD_CFG_PARAM_NR_CHAN];
4418c2ecf20Sopenharmony_ci	memcpy(&pcie->nr_channels, param->data, le32_to_cpu(param->len));
4428c2ecf20Sopenharmony_ci}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_cistatic int kvaser_pciefd_read_cfg(struct kvaser_pciefd *pcie)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	int res;
4478c2ecf20Sopenharmony_ci	struct kvaser_pciefd_cfg_img *img;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	/* Read electronic signature */
4508c2ecf20Sopenharmony_ci	u8 cmd[] = {KVASER_PCIEFD_FLASH_RES_CMD, 0, 0, 0};
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), cmd, 1);
4538c2ecf20Sopenharmony_ci	if (res)
4548c2ecf20Sopenharmony_ci		return -EIO;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	img = kmalloc(KVASER_PCIEFD_CFG_IMG_SZ, GFP_KERNEL);
4578c2ecf20Sopenharmony_ci	if (!img)
4588c2ecf20Sopenharmony_ci		return -ENOMEM;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	if (cmd[0] != KVASER_PCIEFD_FLASH_ID_EPCS16) {
4618c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev,
4628c2ecf20Sopenharmony_ci			"Flash id is 0x%x instead of expected EPCS16 (0x%x)\n",
4638c2ecf20Sopenharmony_ci			cmd[0], KVASER_PCIEFD_FLASH_ID_EPCS16);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci		res = -ENODEV;
4668c2ecf20Sopenharmony_ci		goto image_free;
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	cmd[0] = KVASER_PCIEFD_FLASH_STATUS_CMD;
4708c2ecf20Sopenharmony_ci	res = kvaser_pciefd_spi_cmd(pcie, cmd, 1, cmd, 1);
4718c2ecf20Sopenharmony_ci	if (res) {
4728c2ecf20Sopenharmony_ci		goto image_free;
4738c2ecf20Sopenharmony_ci	} else if (cmd[0] & 1) {
4748c2ecf20Sopenharmony_ci		res = -EIO;
4758c2ecf20Sopenharmony_ci		/* No write is ever done, the WIP should never be set */
4768c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev, "Unexpected WIP bit set in flash\n");
4778c2ecf20Sopenharmony_ci		goto image_free;
4788c2ecf20Sopenharmony_ci	}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	res = kvaser_pciefd_cfg_read_and_verify(pcie, img);
4818c2ecf20Sopenharmony_ci	if (res) {
4828c2ecf20Sopenharmony_ci		res = -EIO;
4838c2ecf20Sopenharmony_ci		goto image_free;
4848c2ecf20Sopenharmony_ci	}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	kvaser_pciefd_cfg_read_params(pcie, img);
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ciimage_free:
4898c2ecf20Sopenharmony_ci	kfree(img);
4908c2ecf20Sopenharmony_ci	return res;
4918c2ecf20Sopenharmony_ci}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_cistatic void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can)
4948c2ecf20Sopenharmony_ci{
4958c2ecf20Sopenharmony_ci	u32 cmd;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	cmd = KVASER_PCIEFD_KCAN_CMD_SRQ;
4988c2ecf20Sopenharmony_ci	cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
4998c2ecf20Sopenharmony_ci	iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_cistatic void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	u32 mode;
5058c2ecf20Sopenharmony_ci	unsigned long irq;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->lock, irq);
5088c2ecf20Sopenharmony_ci	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
5098c2ecf20Sopenharmony_ci	if (!(mode & KVASER_PCIEFD_KCAN_MODE_EPEN)) {
5108c2ecf20Sopenharmony_ci		mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
5118c2ecf20Sopenharmony_ci		iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
5128c2ecf20Sopenharmony_ci	}
5138c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->lock, irq);
5148c2ecf20Sopenharmony_ci}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	u32 mode;
5198c2ecf20Sopenharmony_ci	unsigned long irq;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->lock, irq);
5228c2ecf20Sopenharmony_ci	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
5238c2ecf20Sopenharmony_ci	mode &= ~KVASER_PCIEFD_KCAN_MODE_EPEN;
5248c2ecf20Sopenharmony_ci	iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
5258c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->lock, irq);
5268c2ecf20Sopenharmony_ci}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	u32 msk;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	msk = KVASER_PCIEFD_KCAN_IRQ_TE | KVASER_PCIEFD_KCAN_IRQ_ROF |
5338c2ecf20Sopenharmony_ci	      KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD |
5348c2ecf20Sopenharmony_ci	      KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL |
5358c2ecf20Sopenharmony_ci	      KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP |
5368c2ecf20Sopenharmony_ci	      KVASER_PCIEFD_KCAN_IRQ_TAR;
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	return 0;
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_cistatic void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	u32 mode;
5468c2ecf20Sopenharmony_ci	unsigned long irq;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->lock, irq);
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
5518c2ecf20Sopenharmony_ci	if (can->can.ctrlmode & CAN_CTRLMODE_FD) {
5528c2ecf20Sopenharmony_ci		mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM;
5538c2ecf20Sopenharmony_ci		if (can->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)
5548c2ecf20Sopenharmony_ci			mode |= KVASER_PCIEFD_KCAN_MODE_NIFDEN;
5558c2ecf20Sopenharmony_ci		else
5568c2ecf20Sopenharmony_ci			mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN;
5578c2ecf20Sopenharmony_ci	} else {
5588c2ecf20Sopenharmony_ci		mode |= KVASER_PCIEFD_KCAN_MODE_CCM;
5598c2ecf20Sopenharmony_ci		mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN;
5608c2ecf20Sopenharmony_ci	}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
5638c2ecf20Sopenharmony_ci		mode |= KVASER_PCIEFD_KCAN_MODE_LOM;
5648c2ecf20Sopenharmony_ci	else
5658c2ecf20Sopenharmony_ci		mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	mode |= KVASER_PCIEFD_KCAN_MODE_EEN;
5688c2ecf20Sopenharmony_ci	mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
5698c2ecf20Sopenharmony_ci	/* Use ACK packet type */
5708c2ecf20Sopenharmony_ci	mode &= ~KVASER_PCIEFD_KCAN_MODE_APT;
5718c2ecf20Sopenharmony_ci	mode &= ~KVASER_PCIEFD_KCAN_MODE_RM;
5728c2ecf20Sopenharmony_ci	iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->lock, irq);
5758c2ecf20Sopenharmony_ci}
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_cistatic void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
5788c2ecf20Sopenharmony_ci{
5798c2ecf20Sopenharmony_ci	u32 status;
5808c2ecf20Sopenharmony_ci	unsigned long irq;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->lock, irq);
5838c2ecf20Sopenharmony_ci	iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
5848c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
5858c2ecf20Sopenharmony_ci		  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
5888c2ecf20Sopenharmony_ci	if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
5898c2ecf20Sopenharmony_ci		u32 cmd;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci		/* If controller is already idle, run abort, flush and reset */
5928c2ecf20Sopenharmony_ci		cmd = KVASER_PCIEFD_KCAN_CMD_AT;
5938c2ecf20Sopenharmony_ci		cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
5948c2ecf20Sopenharmony_ci		iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
5958c2ecf20Sopenharmony_ci	} else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) {
5968c2ecf20Sopenharmony_ci		u32 mode;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci		/* Put controller in reset mode */
5998c2ecf20Sopenharmony_ci		mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
6008c2ecf20Sopenharmony_ci		mode |= KVASER_PCIEFD_KCAN_MODE_RM;
6018c2ecf20Sopenharmony_ci		iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->lock, irq);
6058c2ecf20Sopenharmony_ci}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_cistatic int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
6088c2ecf20Sopenharmony_ci{
6098c2ecf20Sopenharmony_ci	u32 mode;
6108c2ecf20Sopenharmony_ci	unsigned long irq;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	del_timer(&can->bec_poll_timer);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	if (!completion_done(&can->flush_comp))
6158c2ecf20Sopenharmony_ci		kvaser_pciefd_start_controller_flush(can);
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	if (!wait_for_completion_timeout(&can->flush_comp,
6188c2ecf20Sopenharmony_ci					 KVASER_PCIEFD_WAIT_TIMEOUT)) {
6198c2ecf20Sopenharmony_ci		netdev_err(can->can.dev, "Timeout during bus on flush\n");
6208c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->lock, irq);
6248c2ecf20Sopenharmony_ci	iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
6258c2ecf20Sopenharmony_ci	iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
6288c2ecf20Sopenharmony_ci		  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
6318c2ecf20Sopenharmony_ci	mode &= ~KVASER_PCIEFD_KCAN_MODE_RM;
6328c2ecf20Sopenharmony_ci	iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
6338c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->lock, irq);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	if (!wait_for_completion_timeout(&can->start_comp,
6368c2ecf20Sopenharmony_ci					 KVASER_PCIEFD_WAIT_TIMEOUT)) {
6378c2ecf20Sopenharmony_ci		netdev_err(can->can.dev, "Timeout during bus on reset\n");
6388c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
6398c2ecf20Sopenharmony_ci	}
6408c2ecf20Sopenharmony_ci	/* Reset interrupt handling */
6418c2ecf20Sopenharmony_ci	iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
6428c2ecf20Sopenharmony_ci	iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	kvaser_pciefd_set_tx_irq(can);
6458c2ecf20Sopenharmony_ci	kvaser_pciefd_setup_controller(can);
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	can->can.state = CAN_STATE_ERROR_ACTIVE;
6488c2ecf20Sopenharmony_ci	netif_wake_queue(can->can.dev);
6498c2ecf20Sopenharmony_ci	can->bec.txerr = 0;
6508c2ecf20Sopenharmony_ci	can->bec.rxerr = 0;
6518c2ecf20Sopenharmony_ci	can->err_rep_cnt = 0;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	return 0;
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cistatic void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	u8 top;
6598c2ecf20Sopenharmony_ci	u32 pwm_ctrl;
6608c2ecf20Sopenharmony_ci	unsigned long irq;
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->lock, irq);
6638c2ecf20Sopenharmony_ci	pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
6648c2ecf20Sopenharmony_ci	top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	/* Set duty cycle to zero */
6678c2ecf20Sopenharmony_ci	pwm_ctrl |= top;
6688c2ecf20Sopenharmony_ci	iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
6698c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->lock, irq);
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistatic void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can)
6738c2ecf20Sopenharmony_ci{
6748c2ecf20Sopenharmony_ci	int top, trigger;
6758c2ecf20Sopenharmony_ci	u32 pwm_ctrl;
6768c2ecf20Sopenharmony_ci	unsigned long irq;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	kvaser_pciefd_pwm_stop(can);
6798c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->lock, irq);
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	/* Set frequency to 500 KHz*/
6828c2ecf20Sopenharmony_ci	top = can->kv_pcie->bus_freq / (2 * 500000) - 1;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	pwm_ctrl = top & 0xff;
6858c2ecf20Sopenharmony_ci	pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
6868c2ecf20Sopenharmony_ci	iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	/* Set duty cycle to 95 */
6898c2ecf20Sopenharmony_ci	trigger = (100 * top - 95 * (top + 1) + 50) / 100;
6908c2ecf20Sopenharmony_ci	pwm_ctrl = trigger & 0xff;
6918c2ecf20Sopenharmony_ci	pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT;
6928c2ecf20Sopenharmony_ci	iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG);
6938c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->lock, irq);
6948c2ecf20Sopenharmony_ci}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_cistatic int kvaser_pciefd_open(struct net_device *netdev)
6978c2ecf20Sopenharmony_ci{
6988c2ecf20Sopenharmony_ci	int err;
6998c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can = netdev_priv(netdev);
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	err = open_candev(netdev);
7028c2ecf20Sopenharmony_ci	if (err)
7038c2ecf20Sopenharmony_ci		return err;
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	err = kvaser_pciefd_bus_on(can);
7068c2ecf20Sopenharmony_ci	if (err) {
7078c2ecf20Sopenharmony_ci		close_candev(netdev);
7088c2ecf20Sopenharmony_ci		return err;
7098c2ecf20Sopenharmony_ci	}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	return 0;
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic int kvaser_pciefd_stop(struct net_device *netdev)
7158c2ecf20Sopenharmony_ci{
7168c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can = netdev_priv(netdev);
7178c2ecf20Sopenharmony_ci	int ret = 0;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	/* Don't interrupt ongoing flush */
7208c2ecf20Sopenharmony_ci	if (!completion_done(&can->flush_comp))
7218c2ecf20Sopenharmony_ci		kvaser_pciefd_start_controller_flush(can);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	if (!wait_for_completion_timeout(&can->flush_comp,
7248c2ecf20Sopenharmony_ci					 KVASER_PCIEFD_WAIT_TIMEOUT)) {
7258c2ecf20Sopenharmony_ci		netdev_err(can->can.dev, "Timeout during stop\n");
7268c2ecf20Sopenharmony_ci		ret = -ETIMEDOUT;
7278c2ecf20Sopenharmony_ci	} else {
7288c2ecf20Sopenharmony_ci		iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
7298c2ecf20Sopenharmony_ci		del_timer(&can->bec_poll_timer);
7308c2ecf20Sopenharmony_ci	}
7318c2ecf20Sopenharmony_ci	can->can.state = CAN_STATE_STOPPED;
7328c2ecf20Sopenharmony_ci	close_candev(netdev);
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	return ret;
7358c2ecf20Sopenharmony_ci}
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_cistatic int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p,
7388c2ecf20Sopenharmony_ci					   struct kvaser_pciefd_can *can,
7398c2ecf20Sopenharmony_ci					   struct sk_buff *skb)
7408c2ecf20Sopenharmony_ci{
7418c2ecf20Sopenharmony_ci	struct canfd_frame *cf = (struct canfd_frame *)skb->data;
7428c2ecf20Sopenharmony_ci	int packet_size;
7438c2ecf20Sopenharmony_ci	int seq = can->echo_idx;
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	memset(p, 0, sizeof(*p));
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
7488c2ecf20Sopenharmony_ci		p->header[1] |= KVASER_PCIEFD_TPACKET_SMS;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	if (cf->can_id & CAN_RTR_FLAG)
7518c2ecf20Sopenharmony_ci		p->header[0] |= KVASER_PCIEFD_RPACKET_RTR;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	if (cf->can_id & CAN_EFF_FLAG)
7548c2ecf20Sopenharmony_ci		p->header[0] |= KVASER_PCIEFD_RPACKET_IDE;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	p->header[0] |= cf->can_id & CAN_EFF_MASK;
7578c2ecf20Sopenharmony_ci	p->header[1] |= can_len2dlc(cf->len) << KVASER_PCIEFD_RPACKET_DLC_SHIFT;
7588c2ecf20Sopenharmony_ci	p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	if (can_is_canfd_skb(skb)) {
7618c2ecf20Sopenharmony_ci		p->header[1] |= KVASER_PCIEFD_RPACKET_FDF;
7628c2ecf20Sopenharmony_ci		if (cf->flags & CANFD_BRS)
7638c2ecf20Sopenharmony_ci			p->header[1] |= KVASER_PCIEFD_RPACKET_BRS;
7648c2ecf20Sopenharmony_ci		if (cf->flags & CANFD_ESI)
7658c2ecf20Sopenharmony_ci			p->header[1] |= KVASER_PCIEFD_RPACKET_ESI;
7668c2ecf20Sopenharmony_ci	}
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	p->header[1] |= seq & KVASER_PCIEFD_PACKET_SEQ_MSK;
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	packet_size = cf->len;
7718c2ecf20Sopenharmony_ci	memcpy(p->data, cf->data, packet_size);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	return DIV_ROUND_UP(packet_size, 4);
7748c2ecf20Sopenharmony_ci}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_cistatic netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
7778c2ecf20Sopenharmony_ci					    struct net_device *netdev)
7788c2ecf20Sopenharmony_ci{
7798c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can = netdev_priv(netdev);
7808c2ecf20Sopenharmony_ci	unsigned long irq_flags;
7818c2ecf20Sopenharmony_ci	struct kvaser_pciefd_tx_packet packet;
7828c2ecf20Sopenharmony_ci	int nwords;
7838c2ecf20Sopenharmony_ci	u8 count;
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	if (can_dropped_invalid_skb(netdev, skb))
7868c2ecf20Sopenharmony_ci		return NETDEV_TX_OK;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->echo_lock, irq_flags);
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	/* Prepare and save echo skb in internal slot */
7938c2ecf20Sopenharmony_ci	can_put_echo_skb(skb, netdev, can->echo_idx);
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	/* Move echo index to the next slot */
7968c2ecf20Sopenharmony_ci	can->echo_idx = (can->echo_idx + 1) % can->can.echo_skb_max;
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	/* Write header to fifo */
7998c2ecf20Sopenharmony_ci	iowrite32(packet.header[0],
8008c2ecf20Sopenharmony_ci		  can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG);
8018c2ecf20Sopenharmony_ci	iowrite32(packet.header[1],
8028c2ecf20Sopenharmony_ci		  can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG);
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	if (nwords) {
8058c2ecf20Sopenharmony_ci		u32 data_last = ((u32 *)packet.data)[nwords - 1];
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci		/* Write data to fifo, except last word */
8088c2ecf20Sopenharmony_ci		iowrite32_rep(can->reg_base +
8098c2ecf20Sopenharmony_ci			      KVASER_PCIEFD_KCAN_FIFO_REG, packet.data,
8108c2ecf20Sopenharmony_ci			      nwords - 1);
8118c2ecf20Sopenharmony_ci		/* Write last word to end of fifo */
8128c2ecf20Sopenharmony_ci		__raw_writel(data_last, can->reg_base +
8138c2ecf20Sopenharmony_ci			     KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
8148c2ecf20Sopenharmony_ci	} else {
8158c2ecf20Sopenharmony_ci		/* Complete write to fifo */
8168c2ecf20Sopenharmony_ci		__raw_writel(0, can->reg_base +
8178c2ecf20Sopenharmony_ci			     KVASER_PCIEFD_KCAN_FIFO_LAST_REG);
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	count = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG);
8218c2ecf20Sopenharmony_ci	/* No room for a new message, stop the queue until at least one
8228c2ecf20Sopenharmony_ci	 * successful transmit
8238c2ecf20Sopenharmony_ci	 */
8248c2ecf20Sopenharmony_ci	if (count >= KVASER_PCIEFD_CAN_TX_MAX_COUNT ||
8258c2ecf20Sopenharmony_ci	    can->can.echo_skb[can->echo_idx])
8268c2ecf20Sopenharmony_ci		netif_stop_queue(netdev);
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->echo_lock, irq_flags);
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
8348c2ecf20Sopenharmony_ci{
8358c2ecf20Sopenharmony_ci	u32 mode, test, btrn;
8368c2ecf20Sopenharmony_ci	unsigned long irq_flags;
8378c2ecf20Sopenharmony_ci	int ret;
8388c2ecf20Sopenharmony_ci	struct can_bittiming *bt;
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	if (data)
8418c2ecf20Sopenharmony_ci		bt = &can->can.data_bittiming;
8428c2ecf20Sopenharmony_ci	else
8438c2ecf20Sopenharmony_ci		bt = &can->can.bittiming;
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	btrn = ((bt->phase_seg2 - 1) & 0x1f) <<
8468c2ecf20Sopenharmony_ci	       KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT |
8478c2ecf20Sopenharmony_ci	       (((bt->prop_seg + bt->phase_seg1) - 1) & 0x1ff) <<
8488c2ecf20Sopenharmony_ci	       KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT |
8498c2ecf20Sopenharmony_ci	       ((bt->sjw - 1) & 0xf) << KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT |
8508c2ecf20Sopenharmony_ci	       ((bt->brp - 1) & 0x1fff);
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	spin_lock_irqsave(&can->lock, irq_flags);
8538c2ecf20Sopenharmony_ci	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	/* Put the circuit in reset mode */
8568c2ecf20Sopenharmony_ci	iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM,
8578c2ecf20Sopenharmony_ci		  can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	/* Can only set bittiming if in reset mode */
8608c2ecf20Sopenharmony_ci	ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG,
8618c2ecf20Sopenharmony_ci				 test, test & KVASER_PCIEFD_KCAN_MODE_RM,
8628c2ecf20Sopenharmony_ci				 0, 10);
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	if (ret) {
8658c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&can->lock, irq_flags);
8668c2ecf20Sopenharmony_ci		return -EBUSY;
8678c2ecf20Sopenharmony_ci	}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	if (data)
8708c2ecf20Sopenharmony_ci		iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG);
8718c2ecf20Sopenharmony_ci	else
8728c2ecf20Sopenharmony_ci		iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG);
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	/* Restore previous reset mode status */
8758c2ecf20Sopenharmony_ci	iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&can->lock, irq_flags);
8788c2ecf20Sopenharmony_ci	return 0;
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_nominal_bittiming(struct net_device *ndev)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	return kvaser_pciefd_set_bittiming(netdev_priv(ndev), false);
8848c2ecf20Sopenharmony_ci}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_data_bittiming(struct net_device *ndev)
8878c2ecf20Sopenharmony_ci{
8888c2ecf20Sopenharmony_ci	return kvaser_pciefd_set_bittiming(netdev_priv(ndev), true);
8898c2ecf20Sopenharmony_ci}
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_mode(struct net_device *ndev, enum can_mode mode)
8928c2ecf20Sopenharmony_ci{
8938c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can = netdev_priv(ndev);
8948c2ecf20Sopenharmony_ci	int ret = 0;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	switch (mode) {
8978c2ecf20Sopenharmony_ci	case CAN_MODE_START:
8988c2ecf20Sopenharmony_ci		if (!can->can.restart_ms)
8998c2ecf20Sopenharmony_ci			ret = kvaser_pciefd_bus_on(can);
9008c2ecf20Sopenharmony_ci		break;
9018c2ecf20Sopenharmony_ci	default:
9028c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
9038c2ecf20Sopenharmony_ci	}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	return ret;
9068c2ecf20Sopenharmony_ci}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_cistatic int kvaser_pciefd_get_berr_counter(const struct net_device *ndev,
9098c2ecf20Sopenharmony_ci					  struct can_berr_counter *bec)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can = netdev_priv(ndev);
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	bec->rxerr = can->bec.rxerr;
9148c2ecf20Sopenharmony_ci	bec->txerr = can->bec.txerr;
9158c2ecf20Sopenharmony_ci	return 0;
9168c2ecf20Sopenharmony_ci}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_cistatic void kvaser_pciefd_bec_poll_timer(struct timer_list *data)
9198c2ecf20Sopenharmony_ci{
9208c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can = from_timer(can, data, bec_poll_timer);
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	kvaser_pciefd_enable_err_gen(can);
9238c2ecf20Sopenharmony_ci	kvaser_pciefd_request_status(can);
9248c2ecf20Sopenharmony_ci	can->err_rep_cnt = 0;
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_cistatic const struct net_device_ops kvaser_pciefd_netdev_ops = {
9288c2ecf20Sopenharmony_ci	.ndo_open = kvaser_pciefd_open,
9298c2ecf20Sopenharmony_ci	.ndo_stop = kvaser_pciefd_stop,
9308c2ecf20Sopenharmony_ci	.ndo_start_xmit = kvaser_pciefd_start_xmit,
9318c2ecf20Sopenharmony_ci	.ndo_change_mtu = can_change_mtu,
9328c2ecf20Sopenharmony_ci};
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_cistatic int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
9358c2ecf20Sopenharmony_ci{
9368c2ecf20Sopenharmony_ci	int i;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	for (i = 0; i < pcie->nr_channels; i++) {
9398c2ecf20Sopenharmony_ci		struct net_device *netdev;
9408c2ecf20Sopenharmony_ci		struct kvaser_pciefd_can *can;
9418c2ecf20Sopenharmony_ci		u32 status, tx_npackets;
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci		netdev = alloc_candev(sizeof(struct kvaser_pciefd_can),
9448c2ecf20Sopenharmony_ci				      KVASER_PCIEFD_CAN_TX_MAX_COUNT);
9458c2ecf20Sopenharmony_ci		if (!netdev)
9468c2ecf20Sopenharmony_ci			return -ENOMEM;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci		can = netdev_priv(netdev);
9498c2ecf20Sopenharmony_ci		netdev->netdev_ops = &kvaser_pciefd_netdev_ops;
9508c2ecf20Sopenharmony_ci		can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE +
9518c2ecf20Sopenharmony_ci				i * KVASER_PCIEFD_KCAN_BASE_OFFSET;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci		can->kv_pcie = pcie;
9548c2ecf20Sopenharmony_ci		can->cmd_seq = 0;
9558c2ecf20Sopenharmony_ci		can->err_rep_cnt = 0;
9568c2ecf20Sopenharmony_ci		can->bec.txerr = 0;
9578c2ecf20Sopenharmony_ci		can->bec.rxerr = 0;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci		init_completion(&can->start_comp);
9608c2ecf20Sopenharmony_ci		init_completion(&can->flush_comp);
9618c2ecf20Sopenharmony_ci		timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer,
9628c2ecf20Sopenharmony_ci			    0);
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci		/* Disable Bus load reporting */
9658c2ecf20Sopenharmony_ci		iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci		tx_npackets = ioread32(can->reg_base +
9688c2ecf20Sopenharmony_ci				       KVASER_PCIEFD_KCAN_TX_NPACKETS_REG);
9698c2ecf20Sopenharmony_ci		if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) &
9708c2ecf20Sopenharmony_ci		      0xff) < KVASER_PCIEFD_CAN_TX_MAX_COUNT) {
9718c2ecf20Sopenharmony_ci			dev_err(&pcie->pci->dev,
9728c2ecf20Sopenharmony_ci				"Max Tx count is smaller than expected\n");
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci			free_candev(netdev);
9758c2ecf20Sopenharmony_ci			return -ENODEV;
9768c2ecf20Sopenharmony_ci		}
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci		can->can.clock.freq = pcie->freq;
9798c2ecf20Sopenharmony_ci		can->can.echo_skb_max = KVASER_PCIEFD_CAN_TX_MAX_COUNT;
9808c2ecf20Sopenharmony_ci		can->echo_idx = 0;
9818c2ecf20Sopenharmony_ci		spin_lock_init(&can->echo_lock);
9828c2ecf20Sopenharmony_ci		spin_lock_init(&can->lock);
9838c2ecf20Sopenharmony_ci		can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
9848c2ecf20Sopenharmony_ci		can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci		can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
9878c2ecf20Sopenharmony_ci		can->can.do_set_data_bittiming =
9888c2ecf20Sopenharmony_ci			kvaser_pciefd_set_data_bittiming;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci		can->can.do_set_mode = kvaser_pciefd_set_mode;
9918c2ecf20Sopenharmony_ci		can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci		can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
9948c2ecf20Sopenharmony_ci					      CAN_CTRLMODE_FD |
9958c2ecf20Sopenharmony_ci					      CAN_CTRLMODE_FD_NON_ISO;
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci		status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
9988c2ecf20Sopenharmony_ci		if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) {
9998c2ecf20Sopenharmony_ci			dev_err(&pcie->pci->dev,
10008c2ecf20Sopenharmony_ci				"CAN FD not supported as expected %d\n", i);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci			free_candev(netdev);
10038c2ecf20Sopenharmony_ci			return -ENODEV;
10048c2ecf20Sopenharmony_ci		}
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci		if (status & KVASER_PCIEFD_KCAN_STAT_CAP)
10078c2ecf20Sopenharmony_ci			can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci		netdev->flags |= IFF_ECHO;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci		SET_NETDEV_DEV(netdev, &pcie->pci->dev);
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci		iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
10148c2ecf20Sopenharmony_ci		iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
10158c2ecf20Sopenharmony_ci			  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci		pcie->can[i] = can;
10188c2ecf20Sopenharmony_ci		kvaser_pciefd_pwm_start(can);
10198c2ecf20Sopenharmony_ci	}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	return 0;
10228c2ecf20Sopenharmony_ci}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_cistatic int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie)
10258c2ecf20Sopenharmony_ci{
10268c2ecf20Sopenharmony_ci	int i;
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	for (i = 0; i < pcie->nr_channels; i++) {
10298c2ecf20Sopenharmony_ci		int err = register_candev(pcie->can[i]->can.dev);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci		if (err) {
10328c2ecf20Sopenharmony_ci			int j;
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci			/* Unregister all successfully registered devices. */
10358c2ecf20Sopenharmony_ci			for (j = 0; j < i; j++)
10368c2ecf20Sopenharmony_ci				unregister_candev(pcie->can[j]->can.dev);
10378c2ecf20Sopenharmony_ci			return err;
10388c2ecf20Sopenharmony_ci		}
10398c2ecf20Sopenharmony_ci	}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	return 0;
10428c2ecf20Sopenharmony_ci}
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_cistatic void kvaser_pciefd_write_dma_map(struct kvaser_pciefd *pcie,
10458c2ecf20Sopenharmony_ci					dma_addr_t addr, int offset)
10468c2ecf20Sopenharmony_ci{
10478c2ecf20Sopenharmony_ci	u32 word1, word2;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
10508c2ecf20Sopenharmony_ci	word1 = addr | KVASER_PCIEFD_64BIT_DMA_BIT;
10518c2ecf20Sopenharmony_ci	word2 = addr >> 32;
10528c2ecf20Sopenharmony_ci#else
10538c2ecf20Sopenharmony_ci	word1 = addr;
10548c2ecf20Sopenharmony_ci	word2 = 0;
10558c2ecf20Sopenharmony_ci#endif
10568c2ecf20Sopenharmony_ci	iowrite32(word1, pcie->reg_base + offset);
10578c2ecf20Sopenharmony_ci	iowrite32(word2, pcie->reg_base + offset + 4);
10588c2ecf20Sopenharmony_ci}
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_cistatic int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
10618c2ecf20Sopenharmony_ci{
10628c2ecf20Sopenharmony_ci	int i;
10638c2ecf20Sopenharmony_ci	u32 srb_status;
10648c2ecf20Sopenharmony_ci	u32 srb_packet_count;
10658c2ecf20Sopenharmony_ci	dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT];
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	/* Disable the DMA */
10688c2ecf20Sopenharmony_ci	iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG);
10698c2ecf20Sopenharmony_ci	for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) {
10708c2ecf20Sopenharmony_ci		unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i;
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci		pcie->dma_data[i] =
10738c2ecf20Sopenharmony_ci			dmam_alloc_coherent(&pcie->pci->dev,
10748c2ecf20Sopenharmony_ci					    KVASER_PCIEFD_DMA_SIZE,
10758c2ecf20Sopenharmony_ci					    &dma_addr[i],
10768c2ecf20Sopenharmony_ci					    GFP_KERNEL);
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci		if (!pcie->dma_data[i] || !dma_addr[i]) {
10798c2ecf20Sopenharmony_ci			dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n",
10808c2ecf20Sopenharmony_ci				KVASER_PCIEFD_DMA_SIZE);
10818c2ecf20Sopenharmony_ci			return -ENOMEM;
10828c2ecf20Sopenharmony_ci		}
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci		kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset);
10858c2ecf20Sopenharmony_ci	}
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	/* Reset Rx FIFO, and both DMA buffers */
10888c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 |
10898c2ecf20Sopenharmony_ci		  KVASER_PCIEFD_SRB_CMD_RDB1,
10908c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	/* Empty Rx FIFO */
10938c2ecf20Sopenharmony_ci	srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) &
10948c2ecf20Sopenharmony_ci			   KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK;
10958c2ecf20Sopenharmony_ci	while (srb_packet_count) {
10968c2ecf20Sopenharmony_ci		/* Drop current packet in FIFO */
10978c2ecf20Sopenharmony_ci		ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
10988c2ecf20Sopenharmony_ci		srb_packet_count--;
10998c2ecf20Sopenharmony_ci	}
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG);
11028c2ecf20Sopenharmony_ci	if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) {
11038c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev, "DMA not idle before enabling\n");
11048c2ecf20Sopenharmony_ci		return -EIO;
11058c2ecf20Sopenharmony_ci	}
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	/* Enable the DMA */
11088c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE,
11098c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG);
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	return 0;
11128c2ecf20Sopenharmony_ci}
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_cistatic int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie)
11158c2ecf20Sopenharmony_ci{
11168c2ecf20Sopenharmony_ci	u32 sysid, srb_status, build;
11178c2ecf20Sopenharmony_ci	u8 sysid_nr_chan;
11188c2ecf20Sopenharmony_ci	int ret;
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	ret = kvaser_pciefd_read_cfg(pcie);
11218c2ecf20Sopenharmony_ci	if (ret)
11228c2ecf20Sopenharmony_ci		return ret;
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	sysid = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG);
11258c2ecf20Sopenharmony_ci	sysid_nr_chan = (sysid >> KVASER_PCIEFD_SYSID_NRCHAN_SHIFT) & 0xff;
11268c2ecf20Sopenharmony_ci	if (pcie->nr_channels != sysid_nr_chan) {
11278c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev,
11288c2ecf20Sopenharmony_ci			"Number of channels does not match: %u vs %u\n",
11298c2ecf20Sopenharmony_ci			pcie->nr_channels,
11308c2ecf20Sopenharmony_ci			sysid_nr_chan);
11318c2ecf20Sopenharmony_ci		return -ENODEV;
11328c2ecf20Sopenharmony_ci	}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	if (pcie->nr_channels > KVASER_PCIEFD_MAX_CAN_CHANNELS)
11358c2ecf20Sopenharmony_ci		pcie->nr_channels = KVASER_PCIEFD_MAX_CAN_CHANNELS;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG);
11388c2ecf20Sopenharmony_ci	dev_dbg(&pcie->pci->dev, "Version %u.%u.%u\n",
11398c2ecf20Sopenharmony_ci		(sysid >> KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT) & 0xff,
11408c2ecf20Sopenharmony_ci		sysid & 0xff,
11418c2ecf20Sopenharmony_ci		(build >> KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT) & 0x7fff);
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG);
11448c2ecf20Sopenharmony_ci	if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) {
11458c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev,
11468c2ecf20Sopenharmony_ci			"Hardware without DMA is not supported\n");
11478c2ecf20Sopenharmony_ci		return -ENODEV;
11488c2ecf20Sopenharmony_ci	}
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	pcie->bus_freq = ioread32(pcie->reg_base +
11518c2ecf20Sopenharmony_ci				  KVASER_PCIEFD_SYSID_BUSFREQ_REG);
11528c2ecf20Sopenharmony_ci	pcie->freq = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_CANFREQ_REG);
11538c2ecf20Sopenharmony_ci	pcie->freq_to_ticks_div = pcie->freq / 1000000;
11548c2ecf20Sopenharmony_ci	if (pcie->freq_to_ticks_div == 0)
11558c2ecf20Sopenharmony_ci		pcie->freq_to_ticks_div = 1;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	/* Turn off all loopback functionality */
11588c2ecf20Sopenharmony_ci	iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG);
11598c2ecf20Sopenharmony_ci	return ret;
11608c2ecf20Sopenharmony_ci}
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie,
11638c2ecf20Sopenharmony_ci					    struct kvaser_pciefd_rx_packet *p,
11648c2ecf20Sopenharmony_ci					    __le32 *data)
11658c2ecf20Sopenharmony_ci{
11668c2ecf20Sopenharmony_ci	struct sk_buff *skb;
11678c2ecf20Sopenharmony_ci	struct canfd_frame *cf;
11688c2ecf20Sopenharmony_ci	struct can_priv *priv;
11698c2ecf20Sopenharmony_ci	struct net_device_stats *stats;
11708c2ecf20Sopenharmony_ci	struct skb_shared_hwtstamps *shhwtstamps;
11718c2ecf20Sopenharmony_ci	u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	if (ch_id >= pcie->nr_channels)
11748c2ecf20Sopenharmony_ci		return -EIO;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	priv = &pcie->can[ch_id]->can;
11778c2ecf20Sopenharmony_ci	stats = &priv->dev->stats;
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) {
11808c2ecf20Sopenharmony_ci		skb = alloc_canfd_skb(priv->dev, &cf);
11818c2ecf20Sopenharmony_ci		if (!skb) {
11828c2ecf20Sopenharmony_ci			stats->rx_dropped++;
11838c2ecf20Sopenharmony_ci			return -ENOMEM;
11848c2ecf20Sopenharmony_ci		}
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci		if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS)
11878c2ecf20Sopenharmony_ci			cf->flags |= CANFD_BRS;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci		if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI)
11908c2ecf20Sopenharmony_ci			cf->flags |= CANFD_ESI;
11918c2ecf20Sopenharmony_ci	} else {
11928c2ecf20Sopenharmony_ci		skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf);
11938c2ecf20Sopenharmony_ci		if (!skb) {
11948c2ecf20Sopenharmony_ci			stats->rx_dropped++;
11958c2ecf20Sopenharmony_ci			return -ENOMEM;
11968c2ecf20Sopenharmony_ci		}
11978c2ecf20Sopenharmony_ci	}
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	cf->can_id = p->header[0] & CAN_EFF_MASK;
12008c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE)
12018c2ecf20Sopenharmony_ci		cf->can_id |= CAN_EFF_FLAG;
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	cf->len = can_dlc2len(p->header[1] >> KVASER_PCIEFD_RPACKET_DLC_SHIFT);
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR)
12068c2ecf20Sopenharmony_ci		cf->can_id |= CAN_RTR_FLAG;
12078c2ecf20Sopenharmony_ci	else
12088c2ecf20Sopenharmony_ci		memcpy(cf->data, data, cf->len);
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	shhwtstamps = skb_hwtstamps(skb);
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	shhwtstamps->hwtstamp =
12138c2ecf20Sopenharmony_ci		ns_to_ktime(div_u64(p->timestamp * 1000,
12148c2ecf20Sopenharmony_ci				    pcie->freq_to_ticks_div));
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	stats->rx_bytes += cf->len;
12178c2ecf20Sopenharmony_ci	stats->rx_packets++;
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	return netif_rx(skb);
12208c2ecf20Sopenharmony_ci}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_cistatic void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can,
12238c2ecf20Sopenharmony_ci				       struct can_frame *cf,
12248c2ecf20Sopenharmony_ci				       enum can_state new_state,
12258c2ecf20Sopenharmony_ci				       enum can_state tx_state,
12268c2ecf20Sopenharmony_ci				       enum can_state rx_state)
12278c2ecf20Sopenharmony_ci{
12288c2ecf20Sopenharmony_ci	can_change_state(can->can.dev, cf, tx_state, rx_state);
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (new_state == CAN_STATE_BUS_OFF) {
12318c2ecf20Sopenharmony_ci		struct net_device *ndev = can->can.dev;
12328c2ecf20Sopenharmony_ci		unsigned long irq_flags;
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci		spin_lock_irqsave(&can->lock, irq_flags);
12358c2ecf20Sopenharmony_ci		netif_stop_queue(can->can.dev);
12368c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&can->lock, irq_flags);
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci		/* Prevent CAN controller from auto recover from bus off */
12398c2ecf20Sopenharmony_ci		if (!can->can.restart_ms) {
12408c2ecf20Sopenharmony_ci			kvaser_pciefd_start_controller_flush(can);
12418c2ecf20Sopenharmony_ci			can_bus_off(ndev);
12428c2ecf20Sopenharmony_ci		}
12438c2ecf20Sopenharmony_ci	}
12448c2ecf20Sopenharmony_ci}
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_cistatic void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p,
12478c2ecf20Sopenharmony_ci					  struct can_berr_counter *bec,
12488c2ecf20Sopenharmony_ci					  enum can_state *new_state,
12498c2ecf20Sopenharmony_ci					  enum can_state *tx_state,
12508c2ecf20Sopenharmony_ci					  enum can_state *rx_state)
12518c2ecf20Sopenharmony_ci{
12528c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF ||
12538c2ecf20Sopenharmony_ci	    p->header[0] & KVASER_PCIEFD_SPACK_IRM)
12548c2ecf20Sopenharmony_ci		*new_state = CAN_STATE_BUS_OFF;
12558c2ecf20Sopenharmony_ci	else if (bec->txerr >= 255 ||  bec->rxerr >= 255)
12568c2ecf20Sopenharmony_ci		*new_state = CAN_STATE_BUS_OFF;
12578c2ecf20Sopenharmony_ci	else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR)
12588c2ecf20Sopenharmony_ci		*new_state = CAN_STATE_ERROR_PASSIVE;
12598c2ecf20Sopenharmony_ci	else if (bec->txerr >= 128 || bec->rxerr >= 128)
12608c2ecf20Sopenharmony_ci		*new_state = CAN_STATE_ERROR_PASSIVE;
12618c2ecf20Sopenharmony_ci	else if (p->header[1] & KVASER_PCIEFD_SPACK_EWLR)
12628c2ecf20Sopenharmony_ci		*new_state = CAN_STATE_ERROR_WARNING;
12638c2ecf20Sopenharmony_ci	else if (bec->txerr >= 96 || bec->rxerr >= 96)
12648c2ecf20Sopenharmony_ci		*new_state = CAN_STATE_ERROR_WARNING;
12658c2ecf20Sopenharmony_ci	else
12668c2ecf20Sopenharmony_ci		*new_state = CAN_STATE_ERROR_ACTIVE;
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	*tx_state = bec->txerr >= bec->rxerr ? *new_state : 0;
12698c2ecf20Sopenharmony_ci	*rx_state = bec->txerr <= bec->rxerr ? *new_state : 0;
12708c2ecf20Sopenharmony_ci}
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_cistatic int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can,
12738c2ecf20Sopenharmony_ci					struct kvaser_pciefd_rx_packet *p)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	struct can_berr_counter bec;
12768c2ecf20Sopenharmony_ci	enum can_state old_state, new_state, tx_state, rx_state;
12778c2ecf20Sopenharmony_ci	struct net_device *ndev = can->can.dev;
12788c2ecf20Sopenharmony_ci	struct sk_buff *skb;
12798c2ecf20Sopenharmony_ci	struct can_frame *cf = NULL;
12808c2ecf20Sopenharmony_ci	struct skb_shared_hwtstamps *shhwtstamps;
12818c2ecf20Sopenharmony_ci	struct net_device_stats *stats = &ndev->stats;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	old_state = can->can.state;
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	bec.txerr = p->header[0] & 0xff;
12868c2ecf20Sopenharmony_ci	bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff;
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state,
12898c2ecf20Sopenharmony_ci				      &rx_state);
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	skb = alloc_can_err_skb(ndev, &cf);
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	if (new_state != old_state) {
12948c2ecf20Sopenharmony_ci		kvaser_pciefd_change_state(can, cf, new_state, tx_state,
12958c2ecf20Sopenharmony_ci					   rx_state);
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci		if (old_state == CAN_STATE_BUS_OFF &&
12988c2ecf20Sopenharmony_ci		    new_state == CAN_STATE_ERROR_ACTIVE &&
12998c2ecf20Sopenharmony_ci		    can->can.restart_ms) {
13008c2ecf20Sopenharmony_ci			can->can.can_stats.restarts++;
13018c2ecf20Sopenharmony_ci			if (skb)
13028c2ecf20Sopenharmony_ci				cf->can_id |= CAN_ERR_RESTARTED;
13038c2ecf20Sopenharmony_ci		}
13048c2ecf20Sopenharmony_ci	}
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	can->err_rep_cnt++;
13078c2ecf20Sopenharmony_ci	can->can.can_stats.bus_error++;
13088c2ecf20Sopenharmony_ci	if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX)
13098c2ecf20Sopenharmony_ci		stats->tx_errors++;
13108c2ecf20Sopenharmony_ci	else
13118c2ecf20Sopenharmony_ci		stats->rx_errors++;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	can->bec.txerr = bec.txerr;
13148c2ecf20Sopenharmony_ci	can->bec.rxerr = bec.rxerr;
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	if (!skb) {
13178c2ecf20Sopenharmony_ci		stats->rx_dropped++;
13188c2ecf20Sopenharmony_ci		return -ENOMEM;
13198c2ecf20Sopenharmony_ci	}
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	shhwtstamps = skb_hwtstamps(skb);
13228c2ecf20Sopenharmony_ci	shhwtstamps->hwtstamp =
13238c2ecf20Sopenharmony_ci		ns_to_ktime(div_u64(p->timestamp * 1000,
13248c2ecf20Sopenharmony_ci				    can->kv_pcie->freq_to_ticks_div));
13258c2ecf20Sopenharmony_ci	cf->can_id |= CAN_ERR_BUSERROR;
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	cf->data[6] = bec.txerr;
13288c2ecf20Sopenharmony_ci	cf->data[7] = bec.rxerr;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	stats->rx_packets++;
13318c2ecf20Sopenharmony_ci	stats->rx_bytes += cf->can_dlc;
13328c2ecf20Sopenharmony_ci
13338c2ecf20Sopenharmony_ci	netif_rx(skb);
13348c2ecf20Sopenharmony_ci	return 0;
13358c2ecf20Sopenharmony_ci}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie,
13388c2ecf20Sopenharmony_ci					     struct kvaser_pciefd_rx_packet *p)
13398c2ecf20Sopenharmony_ci{
13408c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can;
13418c2ecf20Sopenharmony_ci	u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	if (ch_id >= pcie->nr_channels)
13448c2ecf20Sopenharmony_ci		return -EIO;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	can = pcie->can[ch_id];
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci	kvaser_pciefd_rx_error_frame(can, p);
13498c2ecf20Sopenharmony_ci	if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP)
13508c2ecf20Sopenharmony_ci		/* Do not report more errors, until bec_poll_timer expires */
13518c2ecf20Sopenharmony_ci		kvaser_pciefd_disable_err_gen(can);
13528c2ecf20Sopenharmony_ci	/* Start polling the error counters */
13538c2ecf20Sopenharmony_ci	mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
13548c2ecf20Sopenharmony_ci	return 0;
13558c2ecf20Sopenharmony_ci}
13568c2ecf20Sopenharmony_ci
13578c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can,
13588c2ecf20Sopenharmony_ci					    struct kvaser_pciefd_rx_packet *p)
13598c2ecf20Sopenharmony_ci{
13608c2ecf20Sopenharmony_ci	struct can_berr_counter bec;
13618c2ecf20Sopenharmony_ci	enum can_state old_state, new_state, tx_state, rx_state;
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_ci	old_state = can->can.state;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	bec.txerr = p->header[0] & 0xff;
13668c2ecf20Sopenharmony_ci	bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff;
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state,
13698c2ecf20Sopenharmony_ci				      &rx_state);
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci	if (new_state != old_state) {
13728c2ecf20Sopenharmony_ci		struct net_device *ndev = can->can.dev;
13738c2ecf20Sopenharmony_ci		struct sk_buff *skb;
13748c2ecf20Sopenharmony_ci		struct can_frame *cf;
13758c2ecf20Sopenharmony_ci		struct skb_shared_hwtstamps *shhwtstamps;
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci		skb = alloc_can_err_skb(ndev, &cf);
13788c2ecf20Sopenharmony_ci		if (!skb) {
13798c2ecf20Sopenharmony_ci			struct net_device_stats *stats = &ndev->stats;
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci			stats->rx_dropped++;
13828c2ecf20Sopenharmony_ci			return -ENOMEM;
13838c2ecf20Sopenharmony_ci		}
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci		kvaser_pciefd_change_state(can, cf, new_state, tx_state,
13868c2ecf20Sopenharmony_ci					   rx_state);
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci		if (old_state == CAN_STATE_BUS_OFF &&
13898c2ecf20Sopenharmony_ci		    new_state == CAN_STATE_ERROR_ACTIVE &&
13908c2ecf20Sopenharmony_ci		    can->can.restart_ms) {
13918c2ecf20Sopenharmony_ci			can->can.can_stats.restarts++;
13928c2ecf20Sopenharmony_ci			cf->can_id |= CAN_ERR_RESTARTED;
13938c2ecf20Sopenharmony_ci		}
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci		shhwtstamps = skb_hwtstamps(skb);
13968c2ecf20Sopenharmony_ci		shhwtstamps->hwtstamp =
13978c2ecf20Sopenharmony_ci			ns_to_ktime(div_u64(p->timestamp * 1000,
13988c2ecf20Sopenharmony_ci					    can->kv_pcie->freq_to_ticks_div));
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci		cf->data[6] = bec.txerr;
14018c2ecf20Sopenharmony_ci		cf->data[7] = bec.rxerr;
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci		netif_rx(skb);
14048c2ecf20Sopenharmony_ci	}
14058c2ecf20Sopenharmony_ci	can->bec.txerr = bec.txerr;
14068c2ecf20Sopenharmony_ci	can->bec.rxerr = bec.rxerr;
14078c2ecf20Sopenharmony_ci	/* Check if we need to poll the error counters */
14088c2ecf20Sopenharmony_ci	if (bec.txerr || bec.rxerr)
14098c2ecf20Sopenharmony_ci		mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ);
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	return 0;
14128c2ecf20Sopenharmony_ci}
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
14158c2ecf20Sopenharmony_ci					      struct kvaser_pciefd_rx_packet *p)
14168c2ecf20Sopenharmony_ci{
14178c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can;
14188c2ecf20Sopenharmony_ci	u8 cmdseq;
14198c2ecf20Sopenharmony_ci	u32 status;
14208c2ecf20Sopenharmony_ci	u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ci	if (ch_id >= pcie->nr_channels)
14238c2ecf20Sopenharmony_ci		return -EIO;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	can = pcie->can[ch_id];
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
14288c2ecf20Sopenharmony_ci	cmdseq = (status >> KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT) & 0xff;
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	/* Reset done, start abort and flush */
14318c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
14328c2ecf20Sopenharmony_ci	    p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
14338c2ecf20Sopenharmony_ci	    p->header[1] & KVASER_PCIEFD_SPACK_AUTO &&
14348c2ecf20Sopenharmony_ci	    cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
14358c2ecf20Sopenharmony_ci	    status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
14368c2ecf20Sopenharmony_ci		u32 cmd;
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci		iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
14398c2ecf20Sopenharmony_ci			  can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
14408c2ecf20Sopenharmony_ci		cmd = KVASER_PCIEFD_KCAN_CMD_AT;
14418c2ecf20Sopenharmony_ci		cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
14428c2ecf20Sopenharmony_ci		iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
14438c2ecf20Sopenharmony_ci	} else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
14448c2ecf20Sopenharmony_ci		   p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
14458c2ecf20Sopenharmony_ci		   cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
14468c2ecf20Sopenharmony_ci		   status & KVASER_PCIEFD_KCAN_STAT_IDLE) {
14478c2ecf20Sopenharmony_ci		/* Reset detected, send end of flush if no packet are in FIFO */
14488c2ecf20Sopenharmony_ci		u8 count = ioread32(can->reg_base +
14498c2ecf20Sopenharmony_ci				    KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_ci		if (!count)
14528c2ecf20Sopenharmony_ci			iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
14538c2ecf20Sopenharmony_ci				  can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
14548c2ecf20Sopenharmony_ci	} else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) &&
14558c2ecf20Sopenharmony_ci		   cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK)) {
14568c2ecf20Sopenharmony_ci		/* Response to status request received */
14578c2ecf20Sopenharmony_ci		kvaser_pciefd_handle_status_resp(can, p);
14588c2ecf20Sopenharmony_ci		if (can->can.state != CAN_STATE_BUS_OFF &&
14598c2ecf20Sopenharmony_ci		    can->can.state != CAN_STATE_ERROR_ACTIVE) {
14608c2ecf20Sopenharmony_ci			mod_timer(&can->bec_poll_timer,
14618c2ecf20Sopenharmony_ci				  KVASER_PCIEFD_BEC_POLL_FREQ);
14628c2ecf20Sopenharmony_ci		}
14638c2ecf20Sopenharmony_ci	} else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD &&
14648c2ecf20Sopenharmony_ci		   !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK)) {
14658c2ecf20Sopenharmony_ci		/* Reset to bus on detected */
14668c2ecf20Sopenharmony_ci		if (!completion_done(&can->start_comp))
14678c2ecf20Sopenharmony_ci			complete(&can->start_comp);
14688c2ecf20Sopenharmony_ci	}
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	return 0;
14718c2ecf20Sopenharmony_ci}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_eack_packet(struct kvaser_pciefd *pcie,
14748c2ecf20Sopenharmony_ci					    struct kvaser_pciefd_rx_packet *p)
14758c2ecf20Sopenharmony_ci{
14768c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can;
14778c2ecf20Sopenharmony_ci	u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	if (ch_id >= pcie->nr_channels)
14808c2ecf20Sopenharmony_ci		return -EIO;
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	can = pcie->can[ch_id];
14838c2ecf20Sopenharmony_ci
14848c2ecf20Sopenharmony_ci	/* If this is the last flushed packet, send end of flush */
14858c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) {
14868c2ecf20Sopenharmony_ci		u8 count = ioread32(can->reg_base +
14878c2ecf20Sopenharmony_ci				    KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci		if (count == 0)
14908c2ecf20Sopenharmony_ci			iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
14918c2ecf20Sopenharmony_ci				  can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
14928c2ecf20Sopenharmony_ci	} else {
14938c2ecf20Sopenharmony_ci		int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK;
14948c2ecf20Sopenharmony_ci		int dlc = can_get_echo_skb(can->can.dev, echo_idx);
14958c2ecf20Sopenharmony_ci		struct net_device_stats *stats = &can->can.dev->stats;
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci		stats->tx_bytes += dlc;
14988c2ecf20Sopenharmony_ci		stats->tx_packets++;
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci		if (netif_queue_stopped(can->can.dev))
15018c2ecf20Sopenharmony_ci			netif_wake_queue(can->can.dev);
15028c2ecf20Sopenharmony_ci	}
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	return 0;
15058c2ecf20Sopenharmony_ci}
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_cistatic void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can,
15088c2ecf20Sopenharmony_ci					     struct kvaser_pciefd_rx_packet *p)
15098c2ecf20Sopenharmony_ci{
15108c2ecf20Sopenharmony_ci	struct sk_buff *skb;
15118c2ecf20Sopenharmony_ci	struct net_device_stats *stats = &can->can.dev->stats;
15128c2ecf20Sopenharmony_ci	struct can_frame *cf;
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	skb = alloc_can_err_skb(can->can.dev, &cf);
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	stats->tx_errors++;
15178c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) {
15188c2ecf20Sopenharmony_ci		if (skb)
15198c2ecf20Sopenharmony_ci			cf->can_id |= CAN_ERR_LOSTARB;
15208c2ecf20Sopenharmony_ci		can->can.can_stats.arbitration_lost++;
15218c2ecf20Sopenharmony_ci	} else if (skb) {
15228c2ecf20Sopenharmony_ci		cf->can_id |= CAN_ERR_ACK;
15238c2ecf20Sopenharmony_ci	}
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	if (skb) {
15268c2ecf20Sopenharmony_ci		cf->can_id |= CAN_ERR_BUSERROR;
15278c2ecf20Sopenharmony_ci		stats->rx_bytes += cf->can_dlc;
15288c2ecf20Sopenharmony_ci		stats->rx_packets++;
15298c2ecf20Sopenharmony_ci		netif_rx(skb);
15308c2ecf20Sopenharmony_ci	} else {
15318c2ecf20Sopenharmony_ci		stats->rx_dropped++;
15328c2ecf20Sopenharmony_ci		netdev_warn(can->can.dev, "No memory left for err_skb\n");
15338c2ecf20Sopenharmony_ci	}
15348c2ecf20Sopenharmony_ci}
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie,
15378c2ecf20Sopenharmony_ci					   struct kvaser_pciefd_rx_packet *p)
15388c2ecf20Sopenharmony_ci{
15398c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can;
15408c2ecf20Sopenharmony_ci	bool one_shot_fail = false;
15418c2ecf20Sopenharmony_ci	u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	if (ch_id >= pcie->nr_channels)
15448c2ecf20Sopenharmony_ci		return -EIO;
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	can = pcie->can[ch_id];
15478c2ecf20Sopenharmony_ci	/* Ignore control packet ACK */
15488c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_APACKET_CT)
15498c2ecf20Sopenharmony_ci		return 0;
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_APACKET_NACK) {
15528c2ecf20Sopenharmony_ci		kvaser_pciefd_handle_nack_packet(can, p);
15538c2ecf20Sopenharmony_ci		one_shot_fail = true;
15548c2ecf20Sopenharmony_ci	}
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) {
15578c2ecf20Sopenharmony_ci		netdev_dbg(can->can.dev, "Packet was flushed\n");
15588c2ecf20Sopenharmony_ci	} else {
15598c2ecf20Sopenharmony_ci		int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK;
15608c2ecf20Sopenharmony_ci		int dlc = can_get_echo_skb(can->can.dev, echo_idx);
15618c2ecf20Sopenharmony_ci		u8 count = ioread32(can->reg_base +
15628c2ecf20Sopenharmony_ci				    KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci		if (count < KVASER_PCIEFD_CAN_TX_MAX_COUNT &&
15658c2ecf20Sopenharmony_ci		    netif_queue_stopped(can->can.dev))
15668c2ecf20Sopenharmony_ci			netif_wake_queue(can->can.dev);
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci		if (!one_shot_fail) {
15698c2ecf20Sopenharmony_ci			struct net_device_stats *stats = &can->can.dev->stats;
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci			stats->tx_bytes += dlc;
15728c2ecf20Sopenharmony_ci			stats->tx_packets++;
15738c2ecf20Sopenharmony_ci		}
15748c2ecf20Sopenharmony_ci	}
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	return 0;
15778c2ecf20Sopenharmony_ci}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie,
15808c2ecf20Sopenharmony_ci					      struct kvaser_pciefd_rx_packet *p)
15818c2ecf20Sopenharmony_ci{
15828c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can;
15838c2ecf20Sopenharmony_ci	u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7;
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	if (ch_id >= pcie->nr_channels)
15868c2ecf20Sopenharmony_ci		return -EIO;
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	can = pcie->can[ch_id];
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	if (!completion_done(&can->flush_comp))
15918c2ecf20Sopenharmony_ci		complete(&can->flush_comp);
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	return 0;
15948c2ecf20Sopenharmony_ci}
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_cistatic int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
15978c2ecf20Sopenharmony_ci				     int dma_buf)
15988c2ecf20Sopenharmony_ci{
15998c2ecf20Sopenharmony_ci	__le32 *buffer = pcie->dma_data[dma_buf];
16008c2ecf20Sopenharmony_ci	__le64 timestamp;
16018c2ecf20Sopenharmony_ci	struct kvaser_pciefd_rx_packet packet;
16028c2ecf20Sopenharmony_ci	struct kvaser_pciefd_rx_packet *p = &packet;
16038c2ecf20Sopenharmony_ci	u8 type;
16048c2ecf20Sopenharmony_ci	int pos = *start_pos;
16058c2ecf20Sopenharmony_ci	int size;
16068c2ecf20Sopenharmony_ci	int ret = 0;
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	size = le32_to_cpu(buffer[pos++]);
16098c2ecf20Sopenharmony_ci	if (!size) {
16108c2ecf20Sopenharmony_ci		*start_pos = 0;
16118c2ecf20Sopenharmony_ci		return 0;
16128c2ecf20Sopenharmony_ci	}
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	p->header[0] = le32_to_cpu(buffer[pos++]);
16158c2ecf20Sopenharmony_ci	p->header[1] = le32_to_cpu(buffer[pos++]);
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	/* Read 64-bit timestamp */
16188c2ecf20Sopenharmony_ci	memcpy(&timestamp, &buffer[pos], sizeof(__le64));
16198c2ecf20Sopenharmony_ci	pos += 2;
16208c2ecf20Sopenharmony_ci	p->timestamp = le64_to_cpu(timestamp);
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	type = (p->header[1] >> KVASER_PCIEFD_PACKET_TYPE_SHIFT) & 0xf;
16238c2ecf20Sopenharmony_ci	switch (type) {
16248c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_DATA:
16258c2ecf20Sopenharmony_ci		ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]);
16268c2ecf20Sopenharmony_ci		if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) {
16278c2ecf20Sopenharmony_ci			u8 data_len;
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_ci			data_len = can_dlc2len(p->header[1] >>
16308c2ecf20Sopenharmony_ci					       KVASER_PCIEFD_RPACKET_DLC_SHIFT);
16318c2ecf20Sopenharmony_ci			pos += DIV_ROUND_UP(data_len, 4);
16328c2ecf20Sopenharmony_ci		}
16338c2ecf20Sopenharmony_ci		break;
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_ACK:
16368c2ecf20Sopenharmony_ci		ret = kvaser_pciefd_handle_ack_packet(pcie, p);
16378c2ecf20Sopenharmony_ci		break;
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_STATUS:
16408c2ecf20Sopenharmony_ci		ret = kvaser_pciefd_handle_status_packet(pcie, p);
16418c2ecf20Sopenharmony_ci		break;
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_ERROR:
16448c2ecf20Sopenharmony_ci		ret = kvaser_pciefd_handle_error_packet(pcie, p);
16458c2ecf20Sopenharmony_ci		break;
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK:
16488c2ecf20Sopenharmony_ci		ret = kvaser_pciefd_handle_eack_packet(pcie, p);
16498c2ecf20Sopenharmony_ci		break;
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK:
16528c2ecf20Sopenharmony_ci		ret = kvaser_pciefd_handle_eflush_packet(pcie, p);
16538c2ecf20Sopenharmony_ci		break;
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_ACK_DATA:
16568c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD:
16578c2ecf20Sopenharmony_ci	case KVASER_PCIEFD_PACK_TYPE_TXRQ:
16588c2ecf20Sopenharmony_ci		dev_info(&pcie->pci->dev,
16598c2ecf20Sopenharmony_ci			 "Received unexpected packet type 0x%08X\n", type);
16608c2ecf20Sopenharmony_ci		break;
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	default:
16638c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev, "Unknown packet type 0x%08X\n", type);
16648c2ecf20Sopenharmony_ci		ret = -EIO;
16658c2ecf20Sopenharmony_ci		break;
16668c2ecf20Sopenharmony_ci	}
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci	if (ret)
16698c2ecf20Sopenharmony_ci		return ret;
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci	/* Position does not point to the end of the package,
16728c2ecf20Sopenharmony_ci	 * corrupted packet size?
16738c2ecf20Sopenharmony_ci	 */
16748c2ecf20Sopenharmony_ci	if ((*start_pos + size) != pos)
16758c2ecf20Sopenharmony_ci		return -EIO;
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci	/* Point to the next packet header, if any */
16788c2ecf20Sopenharmony_ci	*start_pos = pos;
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci	return ret;
16818c2ecf20Sopenharmony_ci}
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_cistatic int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf)
16848c2ecf20Sopenharmony_ci{
16858c2ecf20Sopenharmony_ci	int pos = 0;
16868c2ecf20Sopenharmony_ci	int res = 0;
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	do {
16898c2ecf20Sopenharmony_ci		res = kvaser_pciefd_read_packet(pcie, &pos, dma_buf);
16908c2ecf20Sopenharmony_ci	} while (!res && pos > 0 && pos < KVASER_PCIEFD_DMA_SIZE);
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	return res;
16938c2ecf20Sopenharmony_ci}
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_cistatic int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
16968c2ecf20Sopenharmony_ci{
16978c2ecf20Sopenharmony_ci	u32 irq;
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	irq = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
17008c2ecf20Sopenharmony_ci	if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) {
17018c2ecf20Sopenharmony_ci		kvaser_pciefd_read_buffer(pcie, 0);
17028c2ecf20Sopenharmony_ci		/* Reset DMA buffer 0 */
17038c2ecf20Sopenharmony_ci		iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
17048c2ecf20Sopenharmony_ci			  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
17058c2ecf20Sopenharmony_ci	}
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci	if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) {
17088c2ecf20Sopenharmony_ci		kvaser_pciefd_read_buffer(pcie, 1);
17098c2ecf20Sopenharmony_ci		/* Reset DMA buffer 1 */
17108c2ecf20Sopenharmony_ci		iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
17118c2ecf20Sopenharmony_ci			  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
17128c2ecf20Sopenharmony_ci	}
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci	if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 ||
17158c2ecf20Sopenharmony_ci	    irq & KVASER_PCIEFD_SRB_IRQ_DOF1 ||
17168c2ecf20Sopenharmony_ci	    irq & KVASER_PCIEFD_SRB_IRQ_DUF0 ||
17178c2ecf20Sopenharmony_ci	    irq & KVASER_PCIEFD_SRB_IRQ_DUF1)
17188c2ecf20Sopenharmony_ci		dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq);
17198c2ecf20Sopenharmony_ci
17208c2ecf20Sopenharmony_ci	iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
17218c2ecf20Sopenharmony_ci	return 0;
17228c2ecf20Sopenharmony_ci}
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_cistatic int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
17258c2ecf20Sopenharmony_ci{
17268c2ecf20Sopenharmony_ci	u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci	if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF)
17298c2ecf20Sopenharmony_ci		netdev_err(can->can.dev, "Tx FIFO overflow\n");
17308c2ecf20Sopenharmony_ci
17318c2ecf20Sopenharmony_ci	if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP)
17328c2ecf20Sopenharmony_ci		netdev_err(can->can.dev,
17338c2ecf20Sopenharmony_ci			   "Fail to change bittiming, when not in reset mode\n");
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	if (irq & KVASER_PCIEFD_KCAN_IRQ_FDIC)
17368c2ecf20Sopenharmony_ci		netdev_err(can->can.dev, "CAN FD frame in CAN mode\n");
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci	if (irq & KVASER_PCIEFD_KCAN_IRQ_ROF)
17398c2ecf20Sopenharmony_ci		netdev_err(can->can.dev, "Rx FIFO overflow\n");
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
17428c2ecf20Sopenharmony_ci	return 0;
17438c2ecf20Sopenharmony_ci}
17448c2ecf20Sopenharmony_ci
17458c2ecf20Sopenharmony_cistatic irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
17468c2ecf20Sopenharmony_ci{
17478c2ecf20Sopenharmony_ci	struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev;
17488c2ecf20Sopenharmony_ci	u32 board_irq;
17498c2ecf20Sopenharmony_ci	int i;
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci	if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MSK))
17548c2ecf20Sopenharmony_ci		return IRQ_NONE;
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci	if (board_irq & KVASER_PCIEFD_IRQ_SRB)
17578c2ecf20Sopenharmony_ci		kvaser_pciefd_receive_irq(pcie);
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	for (i = 0; i < pcie->nr_channels; i++) {
17608c2ecf20Sopenharmony_ci		if (!pcie->can[i]) {
17618c2ecf20Sopenharmony_ci			dev_err(&pcie->pci->dev,
17628c2ecf20Sopenharmony_ci				"IRQ mask points to unallocated controller\n");
17638c2ecf20Sopenharmony_ci			break;
17648c2ecf20Sopenharmony_ci		}
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci		/* Check that mask matches channel (i) IRQ mask */
17678c2ecf20Sopenharmony_ci		if (board_irq & (1 << i))
17688c2ecf20Sopenharmony_ci			kvaser_pciefd_transmit_irq(pcie->can[i]);
17698c2ecf20Sopenharmony_ci	}
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	iowrite32(board_irq, pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
17728c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
17738c2ecf20Sopenharmony_ci}
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_cistatic void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie)
17768c2ecf20Sopenharmony_ci{
17778c2ecf20Sopenharmony_ci	int i;
17788c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can;
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	for (i = 0; i < pcie->nr_channels; i++) {
17818c2ecf20Sopenharmony_ci		can = pcie->can[i];
17828c2ecf20Sopenharmony_ci		if (can) {
17838c2ecf20Sopenharmony_ci			iowrite32(0,
17848c2ecf20Sopenharmony_ci				  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
17858c2ecf20Sopenharmony_ci			kvaser_pciefd_pwm_stop(can);
17868c2ecf20Sopenharmony_ci			free_candev(can->can.dev);
17878c2ecf20Sopenharmony_ci		}
17888c2ecf20Sopenharmony_ci	}
17898c2ecf20Sopenharmony_ci}
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_cistatic int kvaser_pciefd_probe(struct pci_dev *pdev,
17928c2ecf20Sopenharmony_ci			       const struct pci_device_id *id)
17938c2ecf20Sopenharmony_ci{
17948c2ecf20Sopenharmony_ci	int err;
17958c2ecf20Sopenharmony_ci	struct kvaser_pciefd *pcie;
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci	pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
17988c2ecf20Sopenharmony_ci	if (!pcie)
17998c2ecf20Sopenharmony_ci		return -ENOMEM;
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, pcie);
18028c2ecf20Sopenharmony_ci	pcie->pci = pdev;
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	err = pci_enable_device(pdev);
18058c2ecf20Sopenharmony_ci	if (err)
18068c2ecf20Sopenharmony_ci		return err;
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci	err = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME);
18098c2ecf20Sopenharmony_ci	if (err)
18108c2ecf20Sopenharmony_ci		goto err_disable_pci;
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci	pcie->reg_base = pci_iomap(pdev, 0, 0);
18138c2ecf20Sopenharmony_ci	if (!pcie->reg_base) {
18148c2ecf20Sopenharmony_ci		err = -ENOMEM;
18158c2ecf20Sopenharmony_ci		goto err_release_regions;
18168c2ecf20Sopenharmony_ci	}
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_ci	err = kvaser_pciefd_setup_board(pcie);
18198c2ecf20Sopenharmony_ci	if (err)
18208c2ecf20Sopenharmony_ci		goto err_pci_iounmap;
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci	err = kvaser_pciefd_setup_dma(pcie);
18238c2ecf20Sopenharmony_ci	if (err)
18248c2ecf20Sopenharmony_ci		goto err_pci_iounmap;
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	pci_set_master(pdev);
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ci	err = kvaser_pciefd_setup_can_ctrls(pcie);
18298c2ecf20Sopenharmony_ci	if (err)
18308c2ecf20Sopenharmony_ci		goto err_teardown_can_ctrls;
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci	err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
18338c2ecf20Sopenharmony_ci			  IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
18348c2ecf20Sopenharmony_ci	if (err)
18358c2ecf20Sopenharmony_ci		goto err_teardown_can_ctrls;
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1,
18388c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 |
18418c2ecf20Sopenharmony_ci		  KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 |
18428c2ecf20Sopenharmony_ci		  KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1,
18438c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG);
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci	/* Reset IRQ handling, expected to be off before */
18468c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
18478c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
18488c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
18498c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_IEN_REG);
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	/* Ready the DMA buffers */
18528c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
18538c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
18548c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
18558c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci	err = kvaser_pciefd_reg_candev(pcie);
18588c2ecf20Sopenharmony_ci	if (err)
18598c2ecf20Sopenharmony_ci		goto err_free_irq;
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	return 0;
18628c2ecf20Sopenharmony_ci
18638c2ecf20Sopenharmony_cierr_free_irq:
18648c2ecf20Sopenharmony_ci	/* Disable PCI interrupts */
18658c2ecf20Sopenharmony_ci	iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG);
18668c2ecf20Sopenharmony_ci	free_irq(pcie->pci->irq, pcie);
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_cierr_teardown_can_ctrls:
18698c2ecf20Sopenharmony_ci	kvaser_pciefd_teardown_can_ctrls(pcie);
18708c2ecf20Sopenharmony_ci	iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG);
18718c2ecf20Sopenharmony_ci	pci_clear_master(pdev);
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_cierr_pci_iounmap:
18748c2ecf20Sopenharmony_ci	pci_iounmap(pdev, pcie->reg_base);
18758c2ecf20Sopenharmony_ci
18768c2ecf20Sopenharmony_cierr_release_regions:
18778c2ecf20Sopenharmony_ci	pci_release_regions(pdev);
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_cierr_disable_pci:
18808c2ecf20Sopenharmony_ci	pci_disable_device(pdev);
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci	return err;
18838c2ecf20Sopenharmony_ci}
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_cistatic void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie)
18868c2ecf20Sopenharmony_ci{
18878c2ecf20Sopenharmony_ci	struct kvaser_pciefd_can *can;
18888c2ecf20Sopenharmony_ci	int i;
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_ci	for (i = 0; i < pcie->nr_channels; i++) {
18918c2ecf20Sopenharmony_ci		can = pcie->can[i];
18928c2ecf20Sopenharmony_ci		if (can) {
18938c2ecf20Sopenharmony_ci			iowrite32(0,
18948c2ecf20Sopenharmony_ci				  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
18958c2ecf20Sopenharmony_ci			unregister_candev(can->can.dev);
18968c2ecf20Sopenharmony_ci			del_timer(&can->bec_poll_timer);
18978c2ecf20Sopenharmony_ci			kvaser_pciefd_pwm_stop(can);
18988c2ecf20Sopenharmony_ci			free_candev(can->can.dev);
18998c2ecf20Sopenharmony_ci		}
19008c2ecf20Sopenharmony_ci	}
19018c2ecf20Sopenharmony_ci}
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_cistatic void kvaser_pciefd_remove(struct pci_dev *pdev)
19048c2ecf20Sopenharmony_ci{
19058c2ecf20Sopenharmony_ci	struct kvaser_pciefd *pcie = pci_get_drvdata(pdev);
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	kvaser_pciefd_remove_all_ctrls(pcie);
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	/* Turn off IRQ generation */
19108c2ecf20Sopenharmony_ci	iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG);
19118c2ecf20Sopenharmony_ci	iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK,
19128c2ecf20Sopenharmony_ci		  pcie->reg_base + KVASER_PCIEFD_IRQ_REG);
19138c2ecf20Sopenharmony_ci	iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG);
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	free_irq(pcie->pci->irq, pcie);
19168c2ecf20Sopenharmony_ci
19178c2ecf20Sopenharmony_ci	pci_clear_master(pdev);
19188c2ecf20Sopenharmony_ci	pci_iounmap(pdev, pcie->reg_base);
19198c2ecf20Sopenharmony_ci	pci_release_regions(pdev);
19208c2ecf20Sopenharmony_ci	pci_disable_device(pdev);
19218c2ecf20Sopenharmony_ci}
19228c2ecf20Sopenharmony_ci
19238c2ecf20Sopenharmony_cistatic struct pci_driver kvaser_pciefd = {
19248c2ecf20Sopenharmony_ci	.name = KVASER_PCIEFD_DRV_NAME,
19258c2ecf20Sopenharmony_ci	.id_table = kvaser_pciefd_id_table,
19268c2ecf20Sopenharmony_ci	.probe = kvaser_pciefd_probe,
19278c2ecf20Sopenharmony_ci	.remove = kvaser_pciefd_remove,
19288c2ecf20Sopenharmony_ci};
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_cimodule_pci_driver(kvaser_pciefd)
1931