| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2008-2010 Pavel Cheblakov <P.B.Cheblakov@inp.nsk.su> |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com> |
|---|
| 6 | 7 | * Copyright (C) 2008 Markus Plessing <plessing@ems-wuensche.com> |
|---|
| 7 | 8 | * Copyright (C) 2008 Sebastian Haas <haas@ems-wuensche.com> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 10 | | - * it under the terms of the version 2 of the GNU General Public License |
|---|
| 11 | | - * as published by the Free Software Foundation |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | | - * GNU General Public License for more details. |
|---|
| 17 | | - * |
|---|
| 18 | | - * You should have received a copy of the GNU General Public License |
|---|
| 19 | | - * along with this program; if not, see <http://www.gnu.org/licenses/>. |
|---|
| 20 | 9 | */ |
|---|
| 21 | 10 | |
|---|
| 22 | 11 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 46 | 35 | "esd CAN-PCIe/2000, " |
|---|
| 47 | 36 | "Connect Tech Inc. CANpro/104-Plus Opto (CRG001), " |
|---|
| 48 | 37 | "IXXAT PC-I 04/PCI, " |
|---|
| 49 | | - "ELCUS CAN-200-PCI") |
|---|
| 38 | + "ELCUS CAN-200-PCI, " |
|---|
| 39 | + "ASEM DUAL CAN-RAW") |
|---|
| 50 | 40 | MODULE_LICENSE("GPL v2"); |
|---|
| 51 | 41 | |
|---|
| 52 | 42 | #define PLX_PCI_MAX_CHAN 2 |
|---|
| .. | .. |
|---|
| 70 | 60 | */ |
|---|
| 71 | 61 | |
|---|
| 72 | 62 | #define PLX_LINT1_EN 0x1 /* Local interrupt 1 enable */ |
|---|
| 63 | +#define PLX_LINT1_POL (1 << 1) /* Local interrupt 1 polarity */ |
|---|
| 73 | 64 | #define PLX_LINT2_EN (1 << 3) /* Local interrupt 2 enable */ |
|---|
| 65 | +#define PLX_LINT2_POL (1 << 4) /* Local interrupt 2 polarity */ |
|---|
| 74 | 66 | #define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */ |
|---|
| 75 | 67 | #define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */ |
|---|
| 76 | 68 | |
|---|
| .. | .. |
|---|
| 91 | 83 | * This means normal output mode, push-pull and the correct polarity. |
|---|
| 92 | 84 | */ |
|---|
| 93 | 85 | #define PLX_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) |
|---|
| 86 | + |
|---|
| 87 | +/* OCR setting for ASEM Dual CAN raw */ |
|---|
| 88 | +#define ASEM_PCI_OCR 0xfe |
|---|
| 94 | 89 | |
|---|
| 95 | 90 | /* |
|---|
| 96 | 91 | * In the CDR register, you should set CBP to 1. |
|---|
| .. | .. |
|---|
| 145 | 140 | #define MOXA_PCI_VENDOR_ID 0x1393 |
|---|
| 146 | 141 | #define MOXA_PCI_DEVICE_ID 0x0100 |
|---|
| 147 | 142 | |
|---|
| 143 | +#define ASEM_RAW_CAN_VENDOR_ID 0x10b5 |
|---|
| 144 | +#define ASEM_RAW_CAN_DEVICE_ID 0x9030 |
|---|
| 145 | +#define ASEM_RAW_CAN_SUB_VENDOR_ID 0x3000 |
|---|
| 146 | +#define ASEM_RAW_CAN_SUB_DEVICE_ID 0x1001 |
|---|
| 147 | +#define ASEM_RAW_CAN_SUB_DEVICE_ID_BIS 0x1002 |
|---|
| 148 | +#define ASEM_RAW_CAN_RST_REGISTER 0x54 |
|---|
| 149 | +#define ASEM_RAW_CAN_RST_MASK_CAN1 0x20 |
|---|
| 150 | +#define ASEM_RAW_CAN_RST_MASK_CAN2 0x04 |
|---|
| 151 | + |
|---|
| 148 | 152 | static void plx_pci_reset_common(struct pci_dev *pdev); |
|---|
| 149 | 153 | static void plx9056_pci_reset_common(struct pci_dev *pdev); |
|---|
| 150 | 154 | static void plx_pci_reset_marathon_pci(struct pci_dev *pdev); |
|---|
| 151 | 155 | static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev); |
|---|
| 156 | +static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev); |
|---|
| 152 | 157 | |
|---|
| 153 | 158 | struct plx_pci_channel_map { |
|---|
| 154 | 159 | u32 bar; |
|---|
| .. | .. |
|---|
| 269 | 274 | /* based on PLX9052 */ |
|---|
| 270 | 275 | }; |
|---|
| 271 | 276 | |
|---|
| 277 | +static struct plx_pci_card_info plx_pci_card_info_asem_dual_can = { |
|---|
| 278 | + "ASEM Dual CAN raw PCI", 2, |
|---|
| 279 | + PLX_PCI_CAN_CLOCK, ASEM_PCI_OCR, PLX_PCI_CDR, |
|---|
| 280 | + {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} }, |
|---|
| 281 | + &plx_pci_reset_asem_dual_can_raw |
|---|
| 282 | + /* based on PLX9030 */ |
|---|
| 283 | +}; |
|---|
| 284 | + |
|---|
| 272 | 285 | static const struct pci_device_id plx_pci_tbl[] = { |
|---|
| 273 | 286 | { |
|---|
| 274 | 287 | /* Adlink PCI-7841/cPCI-7841 */ |
|---|
| .. | .. |
|---|
| 374 | 387 | PCI_ANY_ID, PCI_ANY_ID, |
|---|
| 375 | 388 | 0, 0, |
|---|
| 376 | 389 | (kernel_ulong_t)&plx_pci_card_info_moxa |
|---|
| 390 | + }, |
|---|
| 391 | + { |
|---|
| 392 | + /* ASEM Dual CAN raw */ |
|---|
| 393 | + ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID, |
|---|
| 394 | + ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID, |
|---|
| 395 | + 0, 0, |
|---|
| 396 | + (kernel_ulong_t)&plx_pci_card_info_asem_dual_can |
|---|
| 397 | + }, |
|---|
| 398 | + { |
|---|
| 399 | + /* ASEM Dual CAN raw -new model */ |
|---|
| 400 | + ASEM_RAW_CAN_VENDOR_ID, ASEM_RAW_CAN_DEVICE_ID, |
|---|
| 401 | + ASEM_RAW_CAN_SUB_VENDOR_ID, ASEM_RAW_CAN_SUB_DEVICE_ID_BIS, |
|---|
| 402 | + 0, 0, |
|---|
| 403 | + (kernel_ulong_t)&plx_pci_card_info_asem_dual_can |
|---|
| 377 | 404 | }, |
|---|
| 378 | 405 | { 0,} |
|---|
| 379 | 406 | }; |
|---|
| .. | .. |
|---|
| 524 | 551 | } |
|---|
| 525 | 552 | } |
|---|
| 526 | 553 | |
|---|
| 554 | +/* Special reset function for ASEM Dual CAN raw card */ |
|---|
| 555 | +static void plx_pci_reset_asem_dual_can_raw(struct pci_dev *pdev) |
|---|
| 556 | +{ |
|---|
| 557 | + void __iomem *bar0_addr; |
|---|
| 558 | + u8 tmpval; |
|---|
| 559 | + |
|---|
| 560 | + plx_pci_reset_common(pdev); |
|---|
| 561 | + |
|---|
| 562 | + bar0_addr = pci_iomap(pdev, 0, 0); |
|---|
| 563 | + if (!bar0_addr) { |
|---|
| 564 | + dev_err(&pdev->dev, "Failed to remap reset space 0 (BAR0)\n"); |
|---|
| 565 | + return; |
|---|
| 566 | + } |
|---|
| 567 | + |
|---|
| 568 | + /* reset the two SJA1000 chips */ |
|---|
| 569 | + tmpval = ioread8(bar0_addr + ASEM_RAW_CAN_RST_REGISTER); |
|---|
| 570 | + tmpval &= ~(ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2); |
|---|
| 571 | + iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER); |
|---|
| 572 | + usleep_range(300, 400); |
|---|
| 573 | + tmpval |= ASEM_RAW_CAN_RST_MASK_CAN1 | ASEM_RAW_CAN_RST_MASK_CAN2; |
|---|
| 574 | + iowrite8(tmpval, bar0_addr + ASEM_RAW_CAN_RST_REGISTER); |
|---|
| 575 | + usleep_range(300, 400); |
|---|
| 576 | + pci_iounmap(pdev, bar0_addr); |
|---|
| 577 | +} |
|---|
| 578 | + |
|---|
| 527 | 579 | static void plx_pci_del_card(struct pci_dev *pdev) |
|---|
| 528 | 580 | { |
|---|
| 529 | 581 | struct plx_pci_card *card = pci_get_drvdata(pdev); |
|---|