Commit b38eb891 authored by Marc Kleine-Budde's avatar Marc Kleine-Budde

Merge patch series "can: kvaser_pciefd: Add support for new Kvaser PCI Express devices"

Jimmy Assarsson <extja@kvaser.com> says:

This patch series adds support for a range of new Kvaser PCI Express
devices based on the SmartFusion2 SoC, to the kvaser_pciefd driver.

In the first patch, the hardware specific constants and functions are
moved into a driver_data struct.

In the second patch, we add the new devices and their hardware
specific constants and functions.

Changes in v2:
- Rebased on
  can: kvaser_pciefd: Fixes and improvements
  https://lore.kernel.org/all/20230529134248.752036-1-extja@kvaser.com
- Dropped
  can: kvaser_pciefd: Wrap register read and writes with macros
  https://lore.kernel.org/linux-can/20230523094354.83792-17-extja@kvaser.com
  since the driver became a lot cleaner when using FIELD_{GET,PREP} and GENMASK.
  Moved some parts of the patch into
  can: kvaser_pciefd: Move hardware specific constants and functions into a driver_data struct
  Removed macros reading/writing registers.
- Link to v1: https://lore.kernel.org/all/20230523094354.83792-14-extja@kvaser.com

Link: https://lore.kernel.org/all/20230622151153.294844-1-extja@kvaser.comSigned-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parents 2e12d79f f33ad677
...@@ -160,8 +160,13 @@ config CAN_KVASER_PCIEFD ...@@ -160,8 +160,13 @@ config CAN_KVASER_PCIEFD
Kvaser PCIEcan 4xHS Kvaser PCIEcan 4xHS
Kvaser PCIEcan 2xHS v2 Kvaser PCIEcan 2xHS v2
Kvaser PCIEcan HS v2 Kvaser PCIEcan HS v2
Kvaser PCIEcan 1xCAN v3
Kvaser PCIEcan 2xCAN v3
Kvaser PCIEcan 4xCAN v2
Kvaser Mini PCI Express HS v2 Kvaser Mini PCI Express HS v2
Kvaser Mini PCI Express 2xHS v2 Kvaser Mini PCI Express 2xHS v2
Kvaser Mini PCI Express 1xCAN v3
Kvaser Mini PCI Express 2xCAN v3
config CAN_SLCAN config CAN_SLCAN
tristate "Serial / USB serial CAN Adaptors (slcan)" tristate "Serial / USB serial CAN Adaptors (slcan)"
......
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved. /* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved.
* Parts of this driver are based on the following: * Parts of this driver are based on the following:
* - Kvaser linux pciefd driver (version 5.25) * - Kvaser linux pciefd driver (version 5.42)
* - PEAK linux canfd driver * - PEAK linux canfd driver
*/ */
...@@ -33,37 +33,27 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); ...@@ -33,37 +33,27 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
#define KVASER_PCIEFD_DMA_SIZE (4U * 1024U) #define KVASER_PCIEFD_DMA_SIZE (4U * 1024U)
#define KVASER_PCIEFD_VENDOR 0x1a07 #define KVASER_PCIEFD_VENDOR 0x1a07
/* Altera based devices */
#define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d #define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d
#define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e #define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e
#define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f #define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f
#define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010 #define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010
#define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011 #define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011
/* PCIe IRQ registers */ /* SmartFusion2 based devices */
#define KVASER_PCIEFD_IRQ_REG 0x40 #define KVASER_PCIEFD_2CAN_V3_DEVICE_ID 0x0012
#define KVASER_PCIEFD_IEN_REG 0x50 #define KVASER_PCIEFD_1CAN_V3_DEVICE_ID 0x0013
/* DMA address translation map register base */ #define KVASER_PCIEFD_4CAN_V2_DEVICE_ID 0x0014
#define KVASER_PCIEFD_DMA_MAP_BASE 0x1000 #define KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID 0x0015
/* Loopback control register */ #define KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID 0x0016
#define KVASER_PCIEFD_LOOP_REG 0x1f000
/* System identification and information registers */ /* Altera SerDes Enable 64-bit DMA address translation */
#define KVASER_PCIEFD_SYSID_BASE 0x1f020 #define KVASER_PCIEFD_ALTERA_DMA_64BIT BIT(0)
#define KVASER_PCIEFD_SYSID_VERSION_REG (KVASER_PCIEFD_SYSID_BASE + 0x8)
#define KVASER_PCIEFD_SYSID_CANFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0xc) /* SmartFusion2 SerDes LSB address translation mask */
#define KVASER_PCIEFD_SYSID_BUSFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0x10) #define KVASER_PCIEFD_SF2_DMA_LSB_MASK GENMASK(31, 12)
#define KVASER_PCIEFD_SYSID_BUILD_REG (KVASER_PCIEFD_SYSID_BASE + 0x14)
/* Shared receive buffer registers */
#define KVASER_PCIEFD_SRB_BASE 0x1f200
#define KVASER_PCIEFD_SRB_FIFO_LAST_REG (KVASER_PCIEFD_SRB_BASE + 0x1f4)
#define KVASER_PCIEFD_SRB_CMD_REG (KVASER_PCIEFD_SRB_BASE + 0x200)
#define KVASER_PCIEFD_SRB_IEN_REG (KVASER_PCIEFD_SRB_BASE + 0x204)
#define KVASER_PCIEFD_SRB_IRQ_REG (KVASER_PCIEFD_SRB_BASE + 0x20c)
#define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210)
#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214)
#define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218)
/* Kvaser KCAN CAN controller registers */ /* Kvaser KCAN CAN controller registers */
#define KVASER_PCIEFD_KCAN0_BASE 0x10000
#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000
#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 #define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 #define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 #define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0
...@@ -77,13 +67,20 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); ...@@ -77,13 +67,20 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424 #define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 #define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
#define KVASER_PCIEFD_KCAN_PWM_REG 0x430 #define KVASER_PCIEFD_KCAN_PWM_REG 0x430
/* System identification and information registers */
/* PCI interrupt fields */ #define KVASER_PCIEFD_SYSID_VERSION_REG 0x8
#define KVASER_PCIEFD_IRQ_SRB BIT(4) #define KVASER_PCIEFD_SYSID_CANFREQ_REG 0xc
#define KVASER_PCIEFD_IRQ_ALL_MASK GENMASK(4, 0) #define KVASER_PCIEFD_SYSID_BUSFREQ_REG 0x10
#define KVASER_PCIEFD_SYSID_BUILD_REG 0x14
/* Enable 64-bit DMA address translation */ /* Shared receive buffer FIFO registers */
#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0) #define KVASER_PCIEFD_SRB_FIFO_LAST_REG 0x1f4
/* Shared receive buffer registers */
#define KVASER_PCIEFD_SRB_CMD_REG 0x0
#define KVASER_PCIEFD_SRB_IEN_REG 0x04
#define KVASER_PCIEFD_SRB_IRQ_REG 0x0c
#define KVASER_PCIEFD_SRB_STAT_REG 0x10
#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG 0x14
#define KVASER_PCIEFD_SRB_CTRL_REG 0x18
/* System build information fields */ /* System build information fields */
#define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24) #define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24)
...@@ -253,7 +250,122 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); ...@@ -253,7 +250,122 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
/* KCAN Error detected packet, second word */ /* KCAN Error detected packet, second word */
#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) #define KVASER_PCIEFD_EPACK_DIR_TX BIT(0)
/* Macros for calculating addresses of registers */
#define KVASER_PCIEFD_GET_BLOCK_ADDR(pcie, block) \
((pcie)->reg_base + (pcie)->driver_data->address_offset->block)
#define KVASER_PCIEFD_PCI_IEN_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_ien))
#define KVASER_PCIEFD_PCI_IRQ_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_irq))
#define KVASER_PCIEFD_SERDES_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), serdes))
#define KVASER_PCIEFD_SYSID_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), sysid))
#define KVASER_PCIEFD_LOOPBACK_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), loopback))
#define KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb_fifo))
#define KVASER_PCIEFD_SRB_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb))
#define KVASER_PCIEFD_KCAN_CH0_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch0))
#define KVASER_PCIEFD_KCAN_CH1_ADDR(pcie) \
(KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch1))
#define KVASER_PCIEFD_KCAN_CHANNEL_SPAN(pcie) \
(KVASER_PCIEFD_KCAN_CH1_ADDR((pcie)) - KVASER_PCIEFD_KCAN_CH0_ADDR((pcie)))
#define KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i) \
(KVASER_PCIEFD_KCAN_CH0_ADDR((pcie)) + (i) * KVASER_PCIEFD_KCAN_CHANNEL_SPAN((pcie)))
struct kvaser_pciefd; struct kvaser_pciefd;
static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie,
dma_addr_t addr, int index);
static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie,
dma_addr_t addr, int index);
struct kvaser_pciefd_address_offset {
u32 serdes;
u32 pci_ien;
u32 pci_irq;
u32 sysid;
u32 loopback;
u32 kcan_srb_fifo;
u32 kcan_srb;
u32 kcan_ch0;
u32 kcan_ch1;
};
struct kvaser_pciefd_dev_ops {
void (*kvaser_pciefd_write_dma_map)(struct kvaser_pciefd *pcie,
dma_addr_t addr, int index);
};
struct kvaser_pciefd_irq_mask {
u32 kcan_rx0;
u32 kcan_tx[KVASER_PCIEFD_MAX_CAN_CHANNELS];
u32 all;
};
struct kvaser_pciefd_driver_data {
const struct kvaser_pciefd_address_offset *address_offset;
const struct kvaser_pciefd_irq_mask *irq_mask;
const struct kvaser_pciefd_dev_ops *ops;
};
static const struct kvaser_pciefd_address_offset kvaser_pciefd_altera_address_offset = {
.serdes = 0x1000,
.pci_ien = 0x50,
.pci_irq = 0x40,
.sysid = 0x1f020,
.loopback = 0x1f000,
.kcan_srb_fifo = 0x1f200,
.kcan_srb = 0x1f400,
.kcan_ch0 = 0x10000,
.kcan_ch1 = 0x11000,
};
static const struct kvaser_pciefd_address_offset kvaser_pciefd_sf2_address_offset = {
.serdes = 0x280c8,
.pci_ien = 0x102004,
.pci_irq = 0x102008,
.sysid = 0x100000,
.loopback = 0x103000,
.kcan_srb_fifo = 0x120000,
.kcan_srb = 0x121000,
.kcan_ch0 = 0x140000,
.kcan_ch1 = 0x142000,
};
static const struct kvaser_pciefd_irq_mask kvaser_pciefd_altera_irq_mask = {
.kcan_rx0 = BIT(4),
.kcan_tx = { BIT(0), BIT(1), BIT(2), BIT(3) },
.all = GENMASK(4, 0),
};
static const struct kvaser_pciefd_irq_mask kvaser_pciefd_sf2_irq_mask = {
.kcan_rx0 = BIT(4),
.kcan_tx = { BIT(16), BIT(17), BIT(18), BIT(19) },
.all = GENMASK(19, 16) | BIT(4),
};
static const struct kvaser_pciefd_dev_ops kvaser_pciefd_altera_dev_ops = {
.kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_altera,
};
static const struct kvaser_pciefd_dev_ops kvaser_pciefd_sf2_dev_ops = {
.kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_sf2,
};
static const struct kvaser_pciefd_driver_data kvaser_pciefd_altera_driver_data = {
.address_offset = &kvaser_pciefd_altera_address_offset,
.irq_mask = &kvaser_pciefd_altera_irq_mask,
.ops = &kvaser_pciefd_altera_dev_ops,
};
static const struct kvaser_pciefd_driver_data kvaser_pciefd_sf2_driver_data = {
.address_offset = &kvaser_pciefd_sf2_address_offset,
.irq_mask = &kvaser_pciefd_sf2_irq_mask,
.ops = &kvaser_pciefd_sf2_dev_ops,
};
struct kvaser_pciefd_can { struct kvaser_pciefd_can {
struct can_priv can; struct can_priv can;
...@@ -273,6 +385,7 @@ struct kvaser_pciefd { ...@@ -273,6 +385,7 @@ struct kvaser_pciefd {
struct pci_dev *pci; struct pci_dev *pci;
void __iomem *reg_base; void __iomem *reg_base;
struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS]; struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS];
const struct kvaser_pciefd_driver_data *driver_data;
void *dma_data[KVASER_PCIEFD_DMA_COUNT]; void *dma_data[KVASER_PCIEFD_DMA_COUNT];
u8 nr_channels; u8 nr_channels;
u32 bus_freq; u32 bus_freq;
...@@ -305,18 +418,43 @@ static const struct can_bittiming_const kvaser_pciefd_bittiming_const = { ...@@ -305,18 +418,43 @@ static const struct can_bittiming_const kvaser_pciefd_bittiming_const = {
static struct pci_device_id kvaser_pciefd_id_table[] = { static struct pci_device_id kvaser_pciefd_id_table[] = {
{ {
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID), PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
}, },
{ {
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID), PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
}, },
{ {
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID), PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
}, },
{ {
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID), PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
}, },
{ {
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID), PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
},
{
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2CAN_V3_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
},
{
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_1CAN_V3_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
},
{
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4CAN_V2_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
},
{
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
},
{
PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID),
.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
}, },
{ {
0, 0,
...@@ -783,8 +921,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) ...@@ -783,8 +921,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
can = netdev_priv(netdev); can = netdev_priv(netdev);
netdev->netdev_ops = &kvaser_pciefd_netdev_ops; netdev->netdev_ops = &kvaser_pciefd_netdev_ops;
netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops; netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops;
can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE + can->reg_base = KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i);
i * KVASER_PCIEFD_KCAN_BASE_OFFSET;
can->kv_pcie = pcie; can->kv_pcie = pcie;
can->cmd_seq = 0; can->cmd_seq = 0;
can->err_rep_cnt = 0; can->err_rep_cnt = 0;
...@@ -865,20 +1002,37 @@ static int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie) ...@@ -865,20 +1002,37 @@ static int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie)
return 0; return 0;
} }
static void kvaser_pciefd_write_dma_map(struct kvaser_pciefd *pcie, static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie,
dma_addr_t addr, int offset) dma_addr_t addr, int index)
{ {
void __iomem *serdes_base;
u32 word1, word2; u32 word1, word2;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
word1 = addr | KVASER_PCIEFD_64BIT_DMA_BIT; word1 = addr | KVASER_PCIEFD_ALTERA_DMA_64BIT;
word2 = addr >> 32; word2 = addr >> 32;
#else #else
word1 = addr; word1 = addr;
word2 = 0; word2 = 0;
#endif #endif
iowrite32(word1, pcie->reg_base + offset); serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x8 * index;
iowrite32(word2, pcie->reg_base + offset + 4); iowrite32(word1, serdes_base);
iowrite32(word2, serdes_base + 0x4);
}
static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie,
dma_addr_t addr, int index)
{
void __iomem *serdes_base;
u32 lsb = addr & KVASER_PCIEFD_SF2_DMA_LSB_MASK;
u32 msb = 0x0;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
msb = addr >> 32;
#endif
serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x10 * index;
iowrite32(lsb, serdes_base);
iowrite32(msb, serdes_base + 0x4);
} }
static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
...@@ -889,10 +1043,8 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) ...@@ -889,10 +1043,8 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT]; dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT];
/* Disable the DMA */ /* Disable the DMA */
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) { for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) {
unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i;
pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev, pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev,
KVASER_PCIEFD_DMA_SIZE, KVASER_PCIEFD_DMA_SIZE,
&dma_addr[i], &dma_addr[i],
...@@ -903,24 +1055,25 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) ...@@ -903,24 +1055,25 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
KVASER_PCIEFD_DMA_SIZE); KVASER_PCIEFD_DMA_SIZE);
return -ENOMEM; return -ENOMEM;
} }
kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset); pcie->driver_data->ops->kvaser_pciefd_write_dma_map(pcie, dma_addr[i], i);
} }
/* Reset Rx FIFO, and both DMA buffers */ /* Reset Rx FIFO, and both DMA buffers */
iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 | iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 |
KVASER_PCIEFD_SRB_CMD_RDB1, KVASER_PCIEFD_SRB_CMD_RDB1,
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
/* Empty Rx FIFO */ /* Empty Rx FIFO */
srb_packet_count = srb_packet_count =
FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK, FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK,
ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG)); ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) +
KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG));
while (srb_packet_count) { while (srb_packet_count) {
/* Drop current packet in FIFO */ /* Drop current packet in FIFO */
ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG); ioread32(KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
srb_packet_count--; srb_packet_count--;
} }
srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG);
if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) { if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) {
dev_err(&pcie->pci->dev, "DMA not idle before enabling\n"); dev_err(&pcie->pci->dev, "DMA not idle before enabling\n");
return -EIO; return -EIO;
...@@ -928,7 +1081,7 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) ...@@ -928,7 +1081,7 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
/* Enable the DMA */ /* Enable the DMA */
iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE, iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE,
pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
return 0; return 0;
} }
...@@ -937,30 +1090,29 @@ static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) ...@@ -937,30 +1090,29 @@ static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie)
{ {
u32 version, srb_status, build; u32 version, srb_status, build;
version = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG); version = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_VERSION_REG);
pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS, pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS,
FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version)); FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version));
build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG); build = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUILD_REG);
dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n", dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n",
FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version), FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version),
FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version), FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version),
FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build)); FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build));
srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG);
if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) { if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) {
dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n"); dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n");
return -ENODEV; return -ENODEV;
} }
pcie->bus_freq = ioread32(pcie->reg_base + pcie->bus_freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUSFREQ_REG);
KVASER_PCIEFD_SYSID_BUSFREQ_REG); pcie->freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_CANFREQ_REG);
pcie->freq = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_CANFREQ_REG);
pcie->freq_to_ticks_div = pcie->freq / 1000000; pcie->freq_to_ticks_div = pcie->freq / 1000000;
if (pcie->freq_to_ticks_div == 0) if (pcie->freq_to_ticks_div == 0)
pcie->freq_to_ticks_div = 1; pcie->freq_to_ticks_div = 1;
/* Turn off all loopback functionality */ /* Turn off all loopback functionality */
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG); iowrite32(0, KVASER_PCIEFD_LOOPBACK_ADDR(pcie));
return 0; return 0;
} }
...@@ -1430,21 +1582,20 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf) ...@@ -1430,21 +1582,20 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf)
static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
{ {
u32 irq; u32 irq = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
irq = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) { if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) {
kvaser_pciefd_read_buffer(pcie, 0); kvaser_pciefd_read_buffer(pcie, 0);
/* Reset DMA buffer 0 */ /* Reset DMA buffer 0 */
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
} }
if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) { if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) {
kvaser_pciefd_read_buffer(pcie, 1); kvaser_pciefd_read_buffer(pcie, 1);
/* Reset DMA buffer 1 */ /* Reset DMA buffer 1 */
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
} }
if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 || if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 ||
...@@ -1453,7 +1604,7 @@ static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) ...@@ -1453,7 +1604,7 @@ static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie)
irq & KVASER_PCIEFD_SRB_IRQ_DUF1) irq & KVASER_PCIEFD_SRB_IRQ_DUF1)
dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq); dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq);
iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); iowrite32(irq, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
} }
static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
...@@ -1479,15 +1630,14 @@ static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) ...@@ -1479,15 +1630,14 @@ static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
{ {
struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev; struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev;
u32 board_irq; const struct kvaser_pciefd_irq_mask *irq_mask = pcie->driver_data->irq_mask;
u32 board_irq = ioread32(KVASER_PCIEFD_PCI_IRQ_ADDR(pcie));
int i; int i;
board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG); if (!(board_irq & irq_mask->all))
if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MASK))
return IRQ_NONE; return IRQ_NONE;
if (board_irq & KVASER_PCIEFD_IRQ_SRB) if (board_irq & irq_mask->kcan_rx0)
kvaser_pciefd_receive_irq(pcie); kvaser_pciefd_receive_irq(pcie);
for (i = 0; i < pcie->nr_channels; i++) { for (i = 0; i < pcie->nr_channels; i++) {
...@@ -1498,7 +1648,7 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) ...@@ -1498,7 +1648,7 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev)
} }
/* Check that mask matches channel (i) IRQ mask */ /* Check that mask matches channel (i) IRQ mask */
if (board_irq & (1 << i)) if (board_irq & irq_mask->kcan_tx[i])
kvaser_pciefd_transmit_irq(pcie->can[i]); kvaser_pciefd_transmit_irq(pcie->can[i]);
} }
...@@ -1525,6 +1675,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, ...@@ -1525,6 +1675,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
{ {
int err; int err;
struct kvaser_pciefd *pcie; struct kvaser_pciefd *pcie;
const struct kvaser_pciefd_irq_mask *irq_mask;
void __iomem *irq_en_base;
pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie) if (!pcie)
...@@ -1532,6 +1684,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, ...@@ -1532,6 +1684,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, pcie); pci_set_drvdata(pdev, pcie);
pcie->pci = pdev; pcie->pci = pdev;
pcie->driver_data = (const struct kvaser_pciefd_driver_data *)id->driver_data;
irq_mask = pcie->driver_data->irq_mask;
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) if (err)
...@@ -1567,22 +1721,21 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, ...@@ -1567,22 +1721,21 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
goto err_teardown_can_ctrls; goto err_teardown_can_ctrls;
iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1, iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1,
pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG);
iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 | iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 |
KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 | KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 |
KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1, KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1,
pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG); KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IEN_REG);
/* Enable PCI interrupts */ /* Enable PCI interrupts */
iowrite32(KVASER_PCIEFD_IRQ_ALL_MASK, irq_en_base = KVASER_PCIEFD_PCI_IEN_ADDR(pcie);
pcie->reg_base + KVASER_PCIEFD_IEN_REG); iowrite32(irq_mask->all, irq_en_base);
/* Ready the DMA buffers */ /* Ready the DMA buffers */
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0,
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG);
err = kvaser_pciefd_reg_candev(pcie); err = kvaser_pciefd_reg_candev(pcie);
if (err) if (err)
...@@ -1592,12 +1745,12 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, ...@@ -1592,12 +1745,12 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
err_free_irq: err_free_irq:
/* Disable PCI interrupts */ /* Disable PCI interrupts */
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); iowrite32(0, irq_en_base);
free_irq(pcie->pci->irq, pcie); free_irq(pcie->pci->irq, pcie);
err_teardown_can_ctrls: err_teardown_can_ctrls:
kvaser_pciefd_teardown_can_ctrls(pcie); kvaser_pciefd_teardown_can_ctrls(pcie);
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
pci_clear_master(pdev); pci_clear_master(pdev);
err_pci_iounmap: err_pci_iounmap:
...@@ -1636,8 +1789,8 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev) ...@@ -1636,8 +1789,8 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev)
kvaser_pciefd_remove_all_ctrls(pcie); kvaser_pciefd_remove_all_ctrls(pcie);
/* Disable interrupts */ /* Disable interrupts */
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG);
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); iowrite32(0, KVASER_PCIEFD_PCI_IEN_ADDR(pcie));
free_irq(pcie->pci->irq, pcie); free_irq(pcie->pci->irq, pcie);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment