diff options
author | Nikita Edward Baruzdin <nebaruzdin@gmail.com> | 2016-04-06 16:04:32 +0300 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2016-05-09 11:07:28 +0200 |
commit | 056a7201ac7a659880b43c2e62a5aa85ca06bebf (patch) | |
tree | aa5d07ac1a397e3e2452134d535b41d5d0514430 /drivers/net | |
parent | 3e51a3356cb2a1a35c07607f93d79484b1496bbf (diff) |
can: sja1000: plx_pci: Add support for Marathon CAN-bus-PCIe card
This patch adds support for the Marathon CAN-bus-PCIe card to the
sja1000 driver. For more information see:
http://can.marathon.ru/page/devices/can-bus-pcie
Signed-off-by: Nikita Edward Baruzdin <nebaruzdin@gmail.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/can/sja1000/plx_pci.c | 64 |
1 files changed, 56 insertions, 8 deletions
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c index 8836a7485c81..3eb7430dffbf 100644 --- a/drivers/net/can/sja1000/plx_pci.c +++ b/drivers/net/can/sja1000/plx_pci.c @@ -39,6 +39,7 @@ MODULE_DESCRIPTION("Socket-CAN driver for PLX90xx PCI-bridge cards with " MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, " "Adlink PCI-7841/cPCI-7841 SE, " "Marathon CAN-bus-PCI, " + "Marathon CAN-bus-PCIe, " "TEWS TECHNOLOGIES TPMC810, " "esd CAN-PCI/CPCI/PCI104/200, " "esd CAN-PCI/PMC/266, " @@ -133,6 +134,7 @@ struct plx_pci_card { #define IXXAT_PCI_SUB_SYS_ID 0x2540 #define MARATHON_PCI_DEVICE_ID 0x2715 +#define MARATHON_PCIE_DEVICE_ID 0x3432 #define TEWS_PCI_VENDOR_ID 0x1498 #define TEWS_PCI_DEVICE_ID_TMPC810 0x032A @@ -141,8 +143,9 @@ struct plx_pci_card { #define CTI_PCI_DEVICE_ID_CRG001 0x0900 static void plx_pci_reset_common(struct pci_dev *pdev); -static void plx_pci_reset_marathon(struct pci_dev *pdev); static void plx9056_pci_reset_common(struct pci_dev *pdev); +static void plx_pci_reset_marathon_pci(struct pci_dev *pdev); +static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev); struct plx_pci_channel_map { u32 bar; @@ -215,14 +218,22 @@ static struct plx_pci_card_info plx_pci_card_info_ixxat = { /* based on PLX9050 */ }; -static struct plx_pci_card_info plx_pci_card_info_marathon = { +static struct plx_pci_card_info plx_pci_card_info_marathon_pci = { "Marathon CAN-bus-PCI", 2, PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} }, - &plx_pci_reset_marathon + &plx_pci_reset_marathon_pci /* based on PLX9052 */ }; +static struct plx_pci_card_info plx_pci_card_info_marathon_pcie = { + "Marathon CAN-bus-PCIe", 2, + PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, + {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {3, 0x80, 0x00} }, + &plx_pci_reset_marathon_pcie + /* based on PEX8311 */ +}; + static struct plx_pci_card_info plx_pci_card_info_tews = { "TEWS TECHNOLOGIES TPMC810", 2, PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, @@ -316,7 +327,14 @@ static const struct pci_device_id plx_pci_tbl[] = { PCI_VENDOR_ID_PLX, MARATHON_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - (kernel_ulong_t)&plx_pci_card_info_marathon + (kernel_ulong_t)&plx_pci_card_info_marathon_pci + }, + { + /* Marathon CAN-bus-PCIe card */ + PCI_VENDOR_ID_PLX, MARATHON_PCIE_DEVICE_ID, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + (kernel_ulong_t)&plx_pci_card_info_marathon_pcie }, { /* TEWS TECHNOLOGIES TPMC810 card */ @@ -437,8 +455,8 @@ static void plx9056_pci_reset_common(struct pci_dev *pdev) iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL); }; -/* Special reset function for Marathon card */ -static void plx_pci_reset_marathon(struct pci_dev *pdev) +/* Special reset function for Marathon CAN-bus-PCI card */ +static void plx_pci_reset_marathon_pci(struct pci_dev *pdev) { void __iomem *reset_addr; int i; @@ -460,6 +478,34 @@ static void plx_pci_reset_marathon(struct pci_dev *pdev) } } +/* Special reset function for Marathon CAN-bus-PCIe card */ +static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev) +{ + void __iomem *addr; + void __iomem *reset_addr; + int i; + + plx9056_pci_reset_common(pdev); + + for (i = 0; i < 2; i++) { + struct plx_pci_channel_map *chan_map = + &plx_pci_card_info_marathon_pcie.chan_map_tbl[i]; + addr = pci_iomap(pdev, chan_map->bar, chan_map->size); + if (!addr) { + dev_err(&pdev->dev, "Failed to remap reset " + "space %d (BAR%d)\n", i, chan_map->bar); + } else { + /* reset the SJA1000 chip */ + #define MARATHON_PCIE_RESET_OFFSET 32 + reset_addr = addr + chan_map->offset + + MARATHON_PCIE_RESET_OFFSET; + iowrite8(0x1, reset_addr); + udelay(100); + pci_iounmap(pdev, addr); + } + } +} + static void plx_pci_del_card(struct pci_dev *pdev) { struct plx_pci_card *card = pci_get_drvdata(pdev); @@ -486,7 +532,8 @@ static void plx_pci_del_card(struct pci_dev *pdev) * Disable interrupts from PCI-card and disable local * interrupts */ - if (pdev->device != PCI_DEVICE_ID_PLX_9056) + if (pdev->device != PCI_DEVICE_ID_PLX_9056 && + pdev->device != MARATHON_PCIE_DEVICE_ID) iowrite32(0x0, card->conf_addr + PLX_INTCSR); else iowrite32(0x0, card->conf_addr + PLX9056_INTCSR); @@ -619,7 +666,8 @@ static int plx_pci_add_card(struct pci_dev *pdev, * Enable interrupts from PCI-card (PLX90xx) and enable Local_1, * Local_2 interrupts from the SJA1000 chips */ - if (pdev->device != PCI_DEVICE_ID_PLX_9056) { + if (pdev->device != PCI_DEVICE_ID_PLX_9056 && + pdev->device != MARATHON_PCIE_DEVICE_ID) { val = ioread32(card->conf_addr + PLX_INTCSR); if (pdev->subsystem_vendor == PCI_VENDOR_ID_ESDGMBH) val |= PLX_LINT1_EN | PLX_PCI_INT_EN; |