|
@@ -41,7 +41,10 @@ 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, "
|
|
|
- "TEWS TECHNOLOGIES TPMC810");
|
|
|
+ "TEWS TECHNOLOGIES TPMC810, "
|
|
|
+ "esd CAN-PCI/CPCI/PCI104/200, "
|
|
|
+ "esd CAN-PCI/PMC/266, "
|
|
|
+ "esd CAN-PCIe/2000")
|
|
|
MODULE_LICENSE("GPL v2");
|
|
|
|
|
|
#define PLX_PCI_MAX_CHAN 2
|
|
@@ -50,11 +53,14 @@ struct plx_pci_card {
|
|
|
int channels; /* detected channels count */
|
|
|
struct net_device *net_dev[PLX_PCI_MAX_CHAN];
|
|
|
void __iomem *conf_addr;
|
|
|
+
|
|
|
+ /* Pointer to device-dependent reset function */
|
|
|
+ void (*reset_func)(struct pci_dev *pdev);
|
|
|
};
|
|
|
|
|
|
#define PLX_PCI_CAN_CLOCK (16000000 / 2)
|
|
|
|
|
|
-/* PLX90xx registers */
|
|
|
+/* PLX9030/9050/9052 registers */
|
|
|
#define PLX_INTCSR 0x4c /* Interrupt Control/Status */
|
|
|
#define PLX_CNTRL 0x50 /* User I/O, Direct Slave Response,
|
|
|
* Serial EEPROM, and Initialization
|
|
@@ -66,6 +72,14 @@ struct plx_pci_card {
|
|
|
#define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */
|
|
|
#define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */
|
|
|
|
|
|
+/* PLX9056 registers */
|
|
|
+#define PLX9056_INTCSR 0x68 /* Interrupt Control/Status */
|
|
|
+#define PLX9056_CNTRL 0x6c /* Control / Software Reset */
|
|
|
+
|
|
|
+#define PLX9056_LINTI (1 << 11)
|
|
|
+#define PLX9056_PCI_INT_EN (1 << 8)
|
|
|
+#define PLX9056_PCI_RCR (1 << 29) /* Read Configuration Registers */
|
|
|
+
|
|
|
/*
|
|
|
* The board configuration is probably following:
|
|
|
* RX1 is connected to ground.
|
|
@@ -101,6 +115,13 @@ struct plx_pci_card {
|
|
|
#define ADLINK_PCI_VENDOR_ID 0x144A
|
|
|
#define ADLINK_PCI_DEVICE_ID 0x7841
|
|
|
|
|
|
+#define ESD_PCI_SUB_SYS_ID_PCI200 0x0004
|
|
|
+#define ESD_PCI_SUB_SYS_ID_PCI266 0x0009
|
|
|
+#define ESD_PCI_SUB_SYS_ID_PMC266 0x000e
|
|
|
+#define ESD_PCI_SUB_SYS_ID_CPCI200 0x010b
|
|
|
+#define ESD_PCI_SUB_SYS_ID_PCIE2000 0x0200
|
|
|
+#define ESD_PCI_SUB_SYS_ID_PCI104200 0x0501
|
|
|
+
|
|
|
#define MARATHON_PCI_DEVICE_ID 0x2715
|
|
|
|
|
|
#define TEWS_PCI_VENDOR_ID 0x1498
|
|
@@ -108,6 +129,7 @@ struct plx_pci_card {
|
|
|
|
|
|
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);
|
|
|
|
|
|
struct plx_pci_channel_map {
|
|
|
u32 bar;
|
|
@@ -148,6 +170,30 @@ static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = {
|
|
|
/* based on PLX9052 */
|
|
|
};
|
|
|
|
|
|
+static struct plx_pci_card_info plx_pci_card_info_esd200 __devinitdata = {
|
|
|
+ "esd CAN-PCI/CPCI/PCI104/200", 2,
|
|
|
+ PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
|
|
|
+ {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
|
|
|
+ &plx_pci_reset_common
|
|
|
+ /* based on PLX9030/9050 */
|
|
|
+};
|
|
|
+
|
|
|
+static struct plx_pci_card_info plx_pci_card_info_esd266 __devinitdata = {
|
|
|
+ "esd CAN-PCI/PMC/266", 2,
|
|
|
+ PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
|
|
|
+ {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
|
|
|
+ &plx9056_pci_reset_common
|
|
|
+ /* based on PLX9056 */
|
|
|
+};
|
|
|
+
|
|
|
+static struct plx_pci_card_info plx_pci_card_info_esd2000 __devinitdata = {
|
|
|
+ "esd CAN-PCIe/2000", 2,
|
|
|
+ PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
|
|
|
+ {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
|
|
|
+ &plx9056_pci_reset_common
|
|
|
+ /* based on PEX8311 */
|
|
|
+};
|
|
|
+
|
|
|
static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = {
|
|
|
"Marathon CAN-bus-PCI", 2,
|
|
|
PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
|
|
@@ -179,6 +225,48 @@ static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
|
|
|
PCI_CLASS_COMMUNICATION_OTHER << 8, ~0,
|
|
|
(kernel_ulong_t)&plx_pci_card_info_adlink_se
|
|
|
},
|
|
|
+ {
|
|
|
+ /* esd CAN-PCI/200 */
|
|
|
+ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
|
|
+ PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCI200,
|
|
|
+ 0, 0,
|
|
|
+ (kernel_ulong_t)&plx_pci_card_info_esd200
|
|
|
+ },
|
|
|
+ {
|
|
|
+ /* esd CAN-CPCI/200 */
|
|
|
+ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
|
|
|
+ PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_CPCI200,
|
|
|
+ 0, 0,
|
|
|
+ (kernel_ulong_t)&plx_pci_card_info_esd200
|
|
|
+ },
|
|
|
+ {
|
|
|
+ /* esd CAN-PCI104/200 */
|
|
|
+ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
|
|
|
+ PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCI104200,
|
|
|
+ 0, 0,
|
|
|
+ (kernel_ulong_t)&plx_pci_card_info_esd200
|
|
|
+ },
|
|
|
+ {
|
|
|
+ /* esd CAN-PCI/266 */
|
|
|
+ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056,
|
|
|
+ PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCI266,
|
|
|
+ 0, 0,
|
|
|
+ (kernel_ulong_t)&plx_pci_card_info_esd266
|
|
|
+ },
|
|
|
+ {
|
|
|
+ /* esd CAN-PMC/266 */
|
|
|
+ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056,
|
|
|
+ PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PMC266,
|
|
|
+ 0, 0,
|
|
|
+ (kernel_ulong_t)&plx_pci_card_info_esd266
|
|
|
+ },
|
|
|
+ {
|
|
|
+ /* esd CAN-PCIE/2000 */
|
|
|
+ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056,
|
|
|
+ PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCIE2000,
|
|
|
+ 0, 0,
|
|
|
+ (kernel_ulong_t)&plx_pci_card_info_esd2000
|
|
|
+ },
|
|
|
{
|
|
|
/* Marathon CAN-bus-PCI card */
|
|
|
PCI_VENDOR_ID_PLX, MARATHON_PCI_DEVICE_ID,
|
|
@@ -242,7 +330,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * PLX90xx software reset
|
|
|
+ * PLX9030/50/52 software reset
|
|
|
* Also LRESET# asserts and brings to reset device on the Local Bus (if wired).
|
|
|
* For most cards it's enough for reset the SJA1000 chips.
|
|
|
*/
|
|
@@ -259,6 +347,38 @@ static void plx_pci_reset_common(struct pci_dev *pdev)
|
|
|
iowrite32(cntrl, card->conf_addr + PLX_CNTRL);
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * PLX9056 software reset
|
|
|
+ * Assert LRESET# and reset device(s) on the Local Bus (if wired).
|
|
|
+ */
|
|
|
+static void plx9056_pci_reset_common(struct pci_dev *pdev)
|
|
|
+{
|
|
|
+ struct plx_pci_card *card = pci_get_drvdata(pdev);
|
|
|
+ u32 cntrl;
|
|
|
+
|
|
|
+ /* issue a local bus reset */
|
|
|
+ cntrl = ioread32(card->conf_addr + PLX9056_CNTRL);
|
|
|
+ cntrl |= PLX_PCI_RESET;
|
|
|
+ iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL);
|
|
|
+ udelay(100);
|
|
|
+ cntrl ^= PLX_PCI_RESET;
|
|
|
+ iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL);
|
|
|
+
|
|
|
+ /* reload local configuration from EEPROM */
|
|
|
+ cntrl |= PLX9056_PCI_RCR;
|
|
|
+ iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * There is no safe way to poll for the end
|
|
|
+ * of reconfiguration process. Waiting for 10ms
|
|
|
+ * is safe.
|
|
|
+ */
|
|
|
+ mdelay(10);
|
|
|
+
|
|
|
+ cntrl ^= PLX9056_PCI_RCR;
|
|
|
+ iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL);
|
|
|
+};
|
|
|
+
|
|
|
/* Special reset function for Marathon card */
|
|
|
static void plx_pci_reset_marathon(struct pci_dev *pdev)
|
|
|
{
|
|
@@ -302,13 +422,16 @@ static void plx_pci_del_card(struct pci_dev *pdev)
|
|
|
free_sja1000dev(dev);
|
|
|
}
|
|
|
|
|
|
- plx_pci_reset_common(pdev);
|
|
|
+ card->reset_func(pdev);
|
|
|
|
|
|
/*
|
|
|
- * Disable interrupts from PCI-card (PLX90xx) and disable Local_1,
|
|
|
- * Local_2 interrupts
|
|
|
+ * Disable interrupts from PCI-card and disable local
|
|
|
+ * interrupts
|
|
|
*/
|
|
|
- iowrite32(0x0, card->conf_addr + PLX_INTCSR);
|
|
|
+ if (pdev->device != PCI_DEVICE_ID_PLX_9056)
|
|
|
+ iowrite32(0x0, card->conf_addr + PLX_INTCSR);
|
|
|
+ else
|
|
|
+ iowrite32(0x0, card->conf_addr + PLX9056_INTCSR);
|
|
|
|
|
|
if (card->conf_addr)
|
|
|
pci_iounmap(pdev, card->conf_addr);
|
|
@@ -367,6 +490,7 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev,
|
|
|
card->conf_addr = addr + ci->conf_map.offset;
|
|
|
|
|
|
ci->reset_func(pdev);
|
|
|
+ card->reset_func = ci->reset_func;
|
|
|
|
|
|
/* Detect available channels */
|
|
|
for (i = 0; i < ci->channel_count; i++) {
|
|
@@ -438,10 +562,17 @@ static int __devinit 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
|
|
|
*/
|
|
|
- val = ioread32(card->conf_addr + PLX_INTCSR);
|
|
|
- val |= PLX_LINT1_EN | PLX_LINT2_EN | PLX_PCI_INT_EN;
|
|
|
- iowrite32(val, card->conf_addr + PLX_INTCSR);
|
|
|
-
|
|
|
+ if (pdev->device != PCI_DEVICE_ID_PLX_9056) {
|
|
|
+ val = ioread32(card->conf_addr + PLX_INTCSR);
|
|
|
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_ESDGMBH)
|
|
|
+ val |= PLX_LINT1_EN | PLX_PCI_INT_EN;
|
|
|
+ else
|
|
|
+ val |= PLX_LINT1_EN | PLX_LINT2_EN | PLX_PCI_INT_EN;
|
|
|
+ iowrite32(val, card->conf_addr + PLX_INTCSR);
|
|
|
+ } else {
|
|
|
+ iowrite32(PLX9056_LINTI | PLX9056_PCI_INT_EN,
|
|
|
+ card->conf_addr + PLX9056_INTCSR);
|
|
|
+ }
|
|
|
return 0;
|
|
|
|
|
|
failure_cleanup:
|