diff options
author | Matthias Fuchs <matthias.fuchs@esd.eu> | 2010-04-06 21:09:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-13 04:23:26 -0400 |
commit | 82e381775f6da6b29ae625e73a2ea18844eb4825 (patch) | |
tree | 365f8d81cbabada143734883b42e2ace938ceeb1 /drivers/net | |
parent | 2e8e18ef52e7dd1af0a3bd1f7d990a1d0b249586 (diff) |
can: Add esd board support to plx_pci CAN driver
This patch adds support for SJA1000 based PCI CAN interface cards
from electronic system design gmbh.
Some changes have been done on the common code:
- esd boards must not have the 2nd local interupt enabled (PLX9030/9050)
- a new path for PLX9056/PEX8311 chips has been added
- new plx9056 reset function has been implemented
- struct plx_card_info got a reset function entry
In detail the following additional boards are now supported:
CAN-PCI/200 (PCI)
CAN-PCI/266 (PCI)
CAN-PMC266 (PMC module)
CAN-PCIe/2000 (PCI Express)
CAN-CPCI/200 (Compact PCI, 3U)
CAN-PCI104 (PCI104)
Signed-off-by: Matthias Fuchs <matthias.fuchs@esd.eu>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/can/sja1000/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/can/sja1000/plx_pci.c | 153 |
2 files changed, 145 insertions, 12 deletions
diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index 9e277d64a318..ae3505afd682 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig | |||
@@ -53,7 +53,9 @@ config CAN_PLX_PCI | |||
53 | Driver supports now: | 53 | Driver supports now: |
54 | - Adlink PCI-7841/cPCI-7841 card (http://www.adlinktech.com/) | 54 | - Adlink PCI-7841/cPCI-7841 card (http://www.adlinktech.com/) |
55 | - Adlink PCI-7841/cPCI-7841 SE card | 55 | - Adlink PCI-7841/cPCI-7841 SE card |
56 | - esd CAN-PCI/CPCI/PCI104/200 (http://www.esd.eu/) | ||
57 | - esd CAN-PCI/PMC/266 | ||
58 | - esd CAN-PCIe/2000 | ||
56 | - Marathon CAN-bus-PCI card (http://www.marathon.ru/) | 59 | - Marathon CAN-bus-PCI card (http://www.marathon.ru/) |
57 | - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/) | 60 | - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/) |
58 | |||
59 | endif | 61 | endif |
diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c index 4aff4070db96..d5efd68085fd 100644 --- a/drivers/net/can/sja1000/plx_pci.c +++ b/drivers/net/can/sja1000/plx_pci.c | |||
@@ -41,7 +41,10 @@ MODULE_DESCRIPTION("Socket-CAN driver for PLX90xx PCI-bridge cards with " | |||
41 | MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, " | 41 | MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, " |
42 | "Adlink PCI-7841/cPCI-7841 SE, " | 42 | "Adlink PCI-7841/cPCI-7841 SE, " |
43 | "Marathon CAN-bus-PCI, " | 43 | "Marathon CAN-bus-PCI, " |
44 | "TEWS TECHNOLOGIES TPMC810"); | 44 | "TEWS TECHNOLOGIES TPMC810, " |
45 | "esd CAN-PCI/CPCI/PCI104/200, " | ||
46 | "esd CAN-PCI/PMC/266, " | ||
47 | "esd CAN-PCIe/2000") | ||
45 | MODULE_LICENSE("GPL v2"); | 48 | MODULE_LICENSE("GPL v2"); |
46 | 49 | ||
47 | #define PLX_PCI_MAX_CHAN 2 | 50 | #define PLX_PCI_MAX_CHAN 2 |
@@ -50,11 +53,14 @@ struct plx_pci_card { | |||
50 | int channels; /* detected channels count */ | 53 | int channels; /* detected channels count */ |
51 | struct net_device *net_dev[PLX_PCI_MAX_CHAN]; | 54 | struct net_device *net_dev[PLX_PCI_MAX_CHAN]; |
52 | void __iomem *conf_addr; | 55 | void __iomem *conf_addr; |
56 | |||
57 | /* Pointer to device-dependent reset function */ | ||
58 | void (*reset_func)(struct pci_dev *pdev); | ||
53 | }; | 59 | }; |
54 | 60 | ||
55 | #define PLX_PCI_CAN_CLOCK (16000000 / 2) | 61 | #define PLX_PCI_CAN_CLOCK (16000000 / 2) |
56 | 62 | ||
57 | /* PLX90xx registers */ | 63 | /* PLX9030/9050/9052 registers */ |
58 | #define PLX_INTCSR 0x4c /* Interrupt Control/Status */ | 64 | #define PLX_INTCSR 0x4c /* Interrupt Control/Status */ |
59 | #define PLX_CNTRL 0x50 /* User I/O, Direct Slave Response, | 65 | #define PLX_CNTRL 0x50 /* User I/O, Direct Slave Response, |
60 | * Serial EEPROM, and Initialization | 66 | * Serial EEPROM, and Initialization |
@@ -66,6 +72,14 @@ struct plx_pci_card { | |||
66 | #define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */ | 72 | #define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */ |
67 | #define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */ | 73 | #define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */ |
68 | 74 | ||
75 | /* PLX9056 registers */ | ||
76 | #define PLX9056_INTCSR 0x68 /* Interrupt Control/Status */ | ||
77 | #define PLX9056_CNTRL 0x6c /* Control / Software Reset */ | ||
78 | |||
79 | #define PLX9056_LINTI (1 << 11) | ||
80 | #define PLX9056_PCI_INT_EN (1 << 8) | ||
81 | #define PLX9056_PCI_RCR (1 << 29) /* Read Configuration Registers */ | ||
82 | |||
69 | /* | 83 | /* |
70 | * The board configuration is probably following: | 84 | * The board configuration is probably following: |
71 | * RX1 is connected to ground. | 85 | * RX1 is connected to ground. |
@@ -101,6 +115,13 @@ struct plx_pci_card { | |||
101 | #define ADLINK_PCI_VENDOR_ID 0x144A | 115 | #define ADLINK_PCI_VENDOR_ID 0x144A |
102 | #define ADLINK_PCI_DEVICE_ID 0x7841 | 116 | #define ADLINK_PCI_DEVICE_ID 0x7841 |
103 | 117 | ||
118 | #define ESD_PCI_SUB_SYS_ID_PCI200 0x0004 | ||
119 | #define ESD_PCI_SUB_SYS_ID_PCI266 0x0009 | ||
120 | #define ESD_PCI_SUB_SYS_ID_PMC266 0x000e | ||
121 | #define ESD_PCI_SUB_SYS_ID_CPCI200 0x010b | ||
122 | #define ESD_PCI_SUB_SYS_ID_PCIE2000 0x0200 | ||
123 | #define ESD_PCI_SUB_SYS_ID_PCI104200 0x0501 | ||
124 | |||
104 | #define MARATHON_PCI_DEVICE_ID 0x2715 | 125 | #define MARATHON_PCI_DEVICE_ID 0x2715 |
105 | 126 | ||
106 | #define TEWS_PCI_VENDOR_ID 0x1498 | 127 | #define TEWS_PCI_VENDOR_ID 0x1498 |
@@ -108,6 +129,7 @@ struct plx_pci_card { | |||
108 | 129 | ||
109 | static void plx_pci_reset_common(struct pci_dev *pdev); | 130 | static void plx_pci_reset_common(struct pci_dev *pdev); |
110 | static void plx_pci_reset_marathon(struct pci_dev *pdev); | 131 | static void plx_pci_reset_marathon(struct pci_dev *pdev); |
132 | static void plx9056_pci_reset_common(struct pci_dev *pdev); | ||
111 | 133 | ||
112 | struct plx_pci_channel_map { | 134 | struct plx_pci_channel_map { |
113 | u32 bar; | 135 | u32 bar; |
@@ -148,6 +170,30 @@ static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = { | |||
148 | /* based on PLX9052 */ | 170 | /* based on PLX9052 */ |
149 | }; | 171 | }; |
150 | 172 | ||
173 | static struct plx_pci_card_info plx_pci_card_info_esd200 __devinitdata = { | ||
174 | "esd CAN-PCI/CPCI/PCI104/200", 2, | ||
175 | PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, | ||
176 | {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} }, | ||
177 | &plx_pci_reset_common | ||
178 | /* based on PLX9030/9050 */ | ||
179 | }; | ||
180 | |||
181 | static struct plx_pci_card_info plx_pci_card_info_esd266 __devinitdata = { | ||
182 | "esd CAN-PCI/PMC/266", 2, | ||
183 | PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, | ||
184 | {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} }, | ||
185 | &plx9056_pci_reset_common | ||
186 | /* based on PLX9056 */ | ||
187 | }; | ||
188 | |||
189 | static struct plx_pci_card_info plx_pci_card_info_esd2000 __devinitdata = { | ||
190 | "esd CAN-PCIe/2000", 2, | ||
191 | PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, | ||
192 | {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} }, | ||
193 | &plx9056_pci_reset_common | ||
194 | /* based on PEX8311 */ | ||
195 | }; | ||
196 | |||
151 | static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = { | 197 | static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = { |
152 | "Marathon CAN-bus-PCI", 2, | 198 | "Marathon CAN-bus-PCI", 2, |
153 | PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, | 199 | PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, |
@@ -180,6 +226,48 @@ static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = { | |||
180 | (kernel_ulong_t)&plx_pci_card_info_adlink_se | 226 | (kernel_ulong_t)&plx_pci_card_info_adlink_se |
181 | }, | 227 | }, |
182 | { | 228 | { |
229 | /* esd CAN-PCI/200 */ | ||
230 | PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, | ||
231 | PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCI200, | ||
232 | 0, 0, | ||
233 | (kernel_ulong_t)&plx_pci_card_info_esd200 | ||
234 | }, | ||
235 | { | ||
236 | /* esd CAN-CPCI/200 */ | ||
237 | PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, | ||
238 | PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_CPCI200, | ||
239 | 0, 0, | ||
240 | (kernel_ulong_t)&plx_pci_card_info_esd200 | ||
241 | }, | ||
242 | { | ||
243 | /* esd CAN-PCI104/200 */ | ||
244 | PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, | ||
245 | PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCI104200, | ||
246 | 0, 0, | ||
247 | (kernel_ulong_t)&plx_pci_card_info_esd200 | ||
248 | }, | ||
249 | { | ||
250 | /* esd CAN-PCI/266 */ | ||
251 | PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056, | ||
252 | PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCI266, | ||
253 | 0, 0, | ||
254 | (kernel_ulong_t)&plx_pci_card_info_esd266 | ||
255 | }, | ||
256 | { | ||
257 | /* esd CAN-PMC/266 */ | ||
258 | PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056, | ||
259 | PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PMC266, | ||
260 | 0, 0, | ||
261 | (kernel_ulong_t)&plx_pci_card_info_esd266 | ||
262 | }, | ||
263 | { | ||
264 | /* esd CAN-PCIE/2000 */ | ||
265 | PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9056, | ||
266 | PCI_VENDOR_ID_ESDGMBH, ESD_PCI_SUB_SYS_ID_PCIE2000, | ||
267 | 0, 0, | ||
268 | (kernel_ulong_t)&plx_pci_card_info_esd2000 | ||
269 | }, | ||
270 | { | ||
183 | /* Marathon CAN-bus-PCI card */ | 271 | /* Marathon CAN-bus-PCI card */ |
184 | PCI_VENDOR_ID_PLX, MARATHON_PCI_DEVICE_ID, | 272 | PCI_VENDOR_ID_PLX, MARATHON_PCI_DEVICE_ID, |
185 | PCI_ANY_ID, PCI_ANY_ID, | 273 | PCI_ANY_ID, PCI_ANY_ID, |
@@ -242,7 +330,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv) | |||
242 | } | 330 | } |
243 | 331 | ||
244 | /* | 332 | /* |
245 | * PLX90xx software reset | 333 | * PLX9030/50/52 software reset |
246 | * Also LRESET# asserts and brings to reset device on the Local Bus (if wired). | 334 | * Also LRESET# asserts and brings to reset device on the Local Bus (if wired). |
247 | * For most cards it's enough for reset the SJA1000 chips. | 335 | * For most cards it's enough for reset the SJA1000 chips. |
248 | */ | 336 | */ |
@@ -259,6 +347,38 @@ static void plx_pci_reset_common(struct pci_dev *pdev) | |||
259 | iowrite32(cntrl, card->conf_addr + PLX_CNTRL); | 347 | iowrite32(cntrl, card->conf_addr + PLX_CNTRL); |
260 | }; | 348 | }; |
261 | 349 | ||
350 | /* | ||
351 | * PLX9056 software reset | ||
352 | * Assert LRESET# and reset device(s) on the Local Bus (if wired). | ||
353 | */ | ||
354 | static void plx9056_pci_reset_common(struct pci_dev *pdev) | ||
355 | { | ||
356 | struct plx_pci_card *card = pci_get_drvdata(pdev); | ||
357 | u32 cntrl; | ||
358 | |||
359 | /* issue a local bus reset */ | ||
360 | cntrl = ioread32(card->conf_addr + PLX9056_CNTRL); | ||
361 | cntrl |= PLX_PCI_RESET; | ||
362 | iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL); | ||
363 | udelay(100); | ||
364 | cntrl ^= PLX_PCI_RESET; | ||
365 | iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL); | ||
366 | |||
367 | /* reload local configuration from EEPROM */ | ||
368 | cntrl |= PLX9056_PCI_RCR; | ||
369 | iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL); | ||
370 | |||
371 | /* | ||
372 | * There is no safe way to poll for the end | ||
373 | * of reconfiguration process. Waiting for 10ms | ||
374 | * is safe. | ||
375 | */ | ||
376 | mdelay(10); | ||
377 | |||
378 | cntrl ^= PLX9056_PCI_RCR; | ||
379 | iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL); | ||
380 | }; | ||
381 | |||
262 | /* Special reset function for Marathon card */ | 382 | /* Special reset function for Marathon card */ |
263 | static void plx_pci_reset_marathon(struct pci_dev *pdev) | 383 | static void plx_pci_reset_marathon(struct pci_dev *pdev) |
264 | { | 384 | { |
@@ -302,13 +422,16 @@ static void plx_pci_del_card(struct pci_dev *pdev) | |||
302 | free_sja1000dev(dev); | 422 | free_sja1000dev(dev); |
303 | } | 423 | } |
304 | 424 | ||
305 | plx_pci_reset_common(pdev); | 425 | card->reset_func(pdev); |
306 | 426 | ||
307 | /* | 427 | /* |
308 | * Disable interrupts from PCI-card (PLX90xx) and disable Local_1, | 428 | * Disable interrupts from PCI-card and disable local |
309 | * Local_2 interrupts | 429 | * interrupts |
310 | */ | 430 | */ |
311 | iowrite32(0x0, card->conf_addr + PLX_INTCSR); | 431 | if (pdev->device != PCI_DEVICE_ID_PLX_9056) |
432 | iowrite32(0x0, card->conf_addr + PLX_INTCSR); | ||
433 | else | ||
434 | iowrite32(0x0, card->conf_addr + PLX9056_INTCSR); | ||
312 | 435 | ||
313 | if (card->conf_addr) | 436 | if (card->conf_addr) |
314 | pci_iounmap(pdev, card->conf_addr); | 437 | pci_iounmap(pdev, card->conf_addr); |
@@ -367,6 +490,7 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev, | |||
367 | card->conf_addr = addr + ci->conf_map.offset; | 490 | card->conf_addr = addr + ci->conf_map.offset; |
368 | 491 | ||
369 | ci->reset_func(pdev); | 492 | ci->reset_func(pdev); |
493 | card->reset_func = ci->reset_func; | ||
370 | 494 | ||
371 | /* Detect available channels */ | 495 | /* Detect available channels */ |
372 | for (i = 0; i < ci->channel_count; i++) { | 496 | for (i = 0; i < ci->channel_count; i++) { |
@@ -438,10 +562,17 @@ static int __devinit plx_pci_add_card(struct pci_dev *pdev, | |||
438 | * Enable interrupts from PCI-card (PLX90xx) and enable Local_1, | 562 | * Enable interrupts from PCI-card (PLX90xx) and enable Local_1, |
439 | * Local_2 interrupts from the SJA1000 chips | 563 | * Local_2 interrupts from the SJA1000 chips |
440 | */ | 564 | */ |
441 | val = ioread32(card->conf_addr + PLX_INTCSR); | 565 | if (pdev->device != PCI_DEVICE_ID_PLX_9056) { |
442 | val |= PLX_LINT1_EN | PLX_LINT2_EN | PLX_PCI_INT_EN; | 566 | val = ioread32(card->conf_addr + PLX_INTCSR); |
443 | iowrite32(val, card->conf_addr + PLX_INTCSR); | 567 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_ESDGMBH) |
444 | 568 | val |= PLX_LINT1_EN | PLX_PCI_INT_EN; | |
569 | else | ||
570 | val |= PLX_LINT1_EN | PLX_LINT2_EN | PLX_PCI_INT_EN; | ||
571 | iowrite32(val, card->conf_addr + PLX_INTCSR); | ||
572 | } else { | ||
573 | iowrite32(PLX9056_LINTI | PLX9056_PCI_INT_EN, | ||
574 | card->conf_addr + PLX9056_INTCSR); | ||
575 | } | ||
445 | return 0; | 576 | return 0; |
446 | 577 | ||
447 | failure_cleanup: | 578 | failure_cleanup: |