]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/esdpci200.c
Added support for ESD PCI/PMC 266 cards.
[lincan.git] / lincan / src / esdpci200.c
1 /* esdpci200.c - support for ESD Electronics' CAN/PCI-200 cards
2  * Linux CAN-bus device driver.
3  * The card support was added by Manuel Bessler <m.bessler@gmx.net>
4  * Based on adlink7841.c and nsi_canpci.c
5  * This software is released under the GPL-License.
6  * Version lincan-0.3.3
7  */ 
8
9 #include "../include/can.h"
10 #include "../include/can_sysdep.h"
11 #include "../include/main.h"
12 #include "../include/sja1000p.h"
13
14 #ifdef CAN_ENABLE_PCI_SUPPORT
15
16 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
17         #define ioread32        can_readl
18         #define iowrite32       can_writel
19         #define ioread8         can_readb
20         #define iowrite8        can_writeb
21         #define wmb()
22         #define rmb()
23 #else
24 #endif
25
26 #define ESDPCI200_PCI_VENDOR_ID 0x10B5
27 #define ESDPCI200_PCI_PRODUCT_ID        0x9050
28
29 /* PCI to local bus bridge PLX9052 */
30
31 #define PLX9052_INTCSR  0x4c    /* interrupt control register */
32 #define PLX9052_CNTRL   0x50    /* control register, for software reset */
33
34 /* The ESD PCI/200 uses (per default) just LINTi1 (Local Interrupt 1)
35  * on the PLX. This means that both CAN channels' (SJA1000's) /INT pins 
36  * are OR'ed to the LINTi1 pin (actually ANDed in the 74HC08 since both
37  * the SJA1000's /INT pins and the LINTi1 pin are active low).
38  *
39  * The board does have an option to route the 2nd channel to LINTi2,
40  * apparently just one or two resistors need to be added.
41  *
42  * LINTi2 is floating per default, so don't set its interrupt enable flag 
43  * 'PLX9052_INTCSR_LI2EN', it'll just interrupt all the time.
44  */
45 #define PLX9052_INTCSR_LI1EN 0x00000001 /* Local Interrupt 1 enable */
46 #define PLX9052_INTCSR_LI1S  0x00000004 /* Local Interrupt 1 status */
47 #define PLX9052_INTCSR_LI2EN 0x00000008 /* Local Interrupt 2 enable */
48 #define PLX9052_INTCSR_LI2S  0x00000020 /* Local Interrupt 2 status */
49 #define PLX9052_INTCSR_PIEN  0x00000040 /* PCI Interrupt enable */
50
51 #define PLX9052_CNTRL_SWRESET 0x40000000 /* PCI Adapter Software Reset to Local Bus */
52
53 #define IO_RANGE 0x100
54
55 // Standard value: Pushpull  (OCTP1|OCTN1|OCPOL1|OCTP0|OCTN0|OCM1)
56 #define ESDPCI200_OCR_DEFAULT_STD 0xFA
57 /* Setting the OCR register to 0xFA is a good idea. 
58    This means  normal output mode , push-pull and the correct polarity. */
59
60
61 void esdpci200_pci_soft_reset(struct candevice_t *candev)
62 {
63         unsigned long reg_reset;
64         reg_reset = inl( candev->res_addr+PLX9052_CNTRL);
65         reg_reset &= ~(PLX9052_CNTRL_SWRESET);
66         rmb();
67         /* PCI Adapter Software Reset plus reset local bus */
68         outl( (reg_reset | PLX9052_CNTRL_SWRESET ), candev->res_addr+PLX9052_CNTRL);
69         wmb();
70         udelay(2500);
71         outl(reg_reset, candev->res_addr+PLX9052_CNTRL);
72         wmb();
73         udelay(2500);
74 }
75
76 void esdpci200_disconnect_irq(struct candevice_t *candev)
77 {
78     /* writing 0x0 into the PLX's INTCSR register disables interrupts */
79         /* 0x0 is also the value in the register after a power-on reset */
80         outl(0x0, candev->res_addr + PLX9052_INTCSR);
81         DEBUGMSG("disabled interrupts on the PLX\n");
82 }
83
84 void esdpci200_connect_irq(struct candevice_t *candev)
85 {
86         /* enable interrupts for the SJA1000's, enable PCI interrupts */
87         outl(   PLX9052_INTCSR_LI1EN | PLX9052_INTCSR_PIEN,
88                 candev->res_addr+PLX9052_INTCSR);
89         DEBUGMSG("enabled interrupts on the PLX\n"); 
90 }
91
92 int esdpci200_irq_handler(int irq, struct canchip_t *chip)
93 {
94         int retcode;
95         unsigned long it_reg;
96         struct candevice_t *candev;
97         candev = chip->hostdevice;
98         retcode = CANCHIP_IRQ_NONE;
99         //DEBUGMSG("Starting to handle an IRQ\n");
100         it_reg = inl(candev->res_addr+PLX9052_INTCSR);
101         rmb();
102         if((it_reg & (PLX9052_INTCSR_LI1S | PLX9052_INTCSR_LI1EN) ) 
103                 == (PLX9052_INTCSR_LI1S | PLX9052_INTCSR_LI1EN) ) 
104         {       /*interrupt enabled and active */
105                 int chipnum;
106                 for(chipnum=0; chipnum < candev->nr_sja1000_chips; chipnum++)
107                 {
108                         if(sja1000p_irq_handler(irq, candev->chip[chipnum]) == CANCHIP_IRQ_NONE)
109                         { /* since both chips use the same IRQ and the same LINTi on the PLX,
110                              we need manually do 'interrupt sharing' on the boardlevel
111                              by checking all chips one-by-one */
112                                 continue;
113                         }
114                         else
115                         {
116                                 retcode=CANCHIP_IRQ_HANDLED;
117                         }
118                 }
119                 if( retcode != CANCHIP_IRQ_HANDLED )
120                 {/* None of the chips felt they were responsible for this IRQ... 
121                     so it appears we have problems with the IRQ */
122                         it_reg &= ~(PLX9052_INTCSR_LI1EN);
123                         //Either we have a problem with IRQ malfunctions, or our IRQ is shared with some other device.
124                         //
125                         //not actually disabled, unless outl() below is uncommented
126                         //outl(it_reg,(void*)(candev->res_addr+PLX9052_INTCSR));
127                         //CANMSG("CAN Interrupt disabled due to malfunction\n");
128                 }
129         }
130         return retcode;
131 }
132
133 int esdpci200_request_io(struct candevice_t *candev)
134 {
135         struct pci_dev *pcidev = candev->sysdevptr.pcidev;
136         can_ioptr_t remap_addr;
137         unsigned long bar2_addr;
138
139         #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
140         if(pci_request_region(pcidev, 0, "esdpci200_plx9050") != 0){
141                 CANMSG("Request of esdpci200_plx9050 range failed\n");
142                 return -ENODEV;
143         }else if(pci_request_region(pcidev, 1, "esdpci200_io") != 0){
144                 CANMSG("Request of esdpci200_io range failed\n");
145                 pci_release_region(pcidev, 0);
146                 return -ENODEV;
147         }else if(pci_request_region(pcidev, 2, "esdpci200_sja") != 0){
148                 CANMSG("Request of esdpci200_sja range failed\n");
149                 pci_release_region(pcidev, 1);
150                 pci_release_region(pcidev, 0);
151                 return -ENODEV;
152         }
153         #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
154         if(pci_request_regions(pcidev, "esdpci200") != 0){
155                 CANMSG("Request of esdpci200_plx9050 regions failed\n");
156                 return -ENODEV;
157         }
158         #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
159
160
161          /* ioports, PLX local configuration registers */
162         candev->res_addr=pci_resource_start(pcidev,1);
163         /*MEM window for SJA1000 chips*/
164         bar2_addr = pci_resource_start(pcidev,2);
165         candev->io_addr = bar2_addr;
166         if( ! (remap_addr=ioremap(bar2_addr, 
167                 pci_resource_len(pcidev,2)))) /*MEM window for SJA1000 chips*/
168         {
169                 CANMSG("Unable to access I/O memory at: 0x%lx\n", (unsigned long)bar2_addr);
170                 goto ioremap_error;
171         }
172
173         can_base_addr_fixup(candev, remap_addr);
174         CANMSG("esdpci200_sja IO-memory: 0x%lx - 0x%lx (VMA 0x%lx)\n", 
175                 (unsigned long) bar2_addr,
176                 (unsigned long) (bar2_addr + pci_resource_len(pcidev,2) - 1),
177                 (long) remap_addr);
178
179         return 0;
180
181     ioremap_error:
182 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
183         pci_release_region(pcidev, 2);
184         pci_release_region(pcidev, 1);
185         pci_release_region(pcidev, 0);
186 #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
187         pci_release_regions(pcidev);
188 #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
189         return -ENODEV;
190 }
191
192 int esdpci200_release_io(struct candevice_t *candev)
193 {
194         esdpci200_disconnect_irq(candev);
195         esdpci200_pci_soft_reset(candev);
196
197         iounmap(candev->dev_base_addr);
198     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
199         pci_release_region(candev->sysdevptr.pcidev, 2);
200         pci_release_region(candev->sysdevptr.pcidev, 1);
201         pci_release_region(candev->sysdevptr.pcidev, 0);
202     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
203         pci_release_regions(candev->sysdevptr.pcidev);
204     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
205
206         return 0;
207 }
208
209 void esdpci200_write_register(unsigned data, can_ioptr_t address)
210 {
211         iowrite8((u8)data,address);
212         wmb();
213 }
214
215 unsigned esdpci200_read_register(can_ioptr_t address)
216 {
217         return ioread8(address);
218 }
219
220 int esdpci200_reset(struct candevice_t *candev)
221 {
222         int i=0,chip_nr;
223         struct canchip_t *chip;
224         unsigned cdr;
225         DEBUGMSG("Resetting esdpci200 hardware ...\n");
226
227         esdpci200_disconnect_irq(candev);
228         esdpci200_pci_soft_reset(candev);
229
230         for(chip_nr=0;chip_nr<candev->nr_all_chips;chip_nr++){
231                 if(!candev->chip[chip_nr]) continue;
232                 chip=candev->chip[chip_nr];
233
234                 esdpci200_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
235                 udelay(1000);
236
237                 cdr=esdpci200_read_register(chip->chip_base_addr+SJACDR);
238                 esdpci200_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
239
240                 esdpci200_write_register(0, chip->chip_base_addr+SJAIER);
241
242                 i=20;
243                 esdpci200_write_register(0, chip->chip_base_addr+SJAMOD);
244                 while (esdpci200_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
245                         if(!i--) return -ENODEV;
246                         udelay(1000);
247                         esdpci200_write_register(0, chip->chip_base_addr+SJAMOD);
248                 }
249
250                 cdr=esdpci200_read_register(chip->chip_base_addr+SJACDR);
251                 esdpci200_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
252
253                 esdpci200_write_register(0, chip->chip_base_addr+SJAIER);
254                 
255                 esdpci200_read_register(chip->chip_base_addr+SJAIR);
256         }
257         
258
259         esdpci200_connect_irq(candev);
260
261         return 0;
262 }       
263
264 int esdpci200_init_hw_data(struct candevice_t *candev)
265 {
266         struct pci_dev *pcidev = NULL;
267
268         do {
269                 pcidev = pci_find_device(ESDPCI200_PCI_VENDOR_ID, ESDPCI200_PCI_PRODUCT_ID, pcidev);
270                 if(pcidev == NULL) return -ENODEV;
271         } while(can_check_dev_taken(pcidev));
272         
273         if (pci_enable_device (pcidev)){
274                 printk(KERN_CRIT "Setup of ESDPCI200 failed\n");
275                 return -EIO;
276         }
277         candev->sysdevptr.pcidev=pcidev;
278
279         can_spin_lock_init(&candev->device_lock);
280
281         if(!(pci_resource_flags(pcidev, 0)&IORESOURCE_MEM))
282         {
283            printk(KERN_CRIT "PCI200 region %d is not MEM\n",0);
284            return -EIO;
285         }
286         if(!(pci_resource_flags(pcidev, 1)&IORESOURCE_IO))
287         {
288            printk(KERN_CRIT "PCI200 region %d is not IO\n",1);
289            return -EIO;
290         }
291
292         if(!(pci_resource_flags(pcidev,2)&IORESOURCE_MEM))
293         {
294            printk(KERN_CRIT "PCI200 region %d is not MEM\n",2);
295            return -EIO;
296         }
297
298          /* Reset/control field - used to store port of PLX9052 control region */
299         candev->res_addr = pci_resource_start(pcidev,1);;
300
301         /* Physical address of SJA1000 window, stored for debugging only */
302         candev->io_addr = pci_resource_start(pcidev,2);
303         
304         candev->aux_base_addr=NULL; /* mapped dynamically in esdpci200_request_io() */
305         candev->dev_base_addr=NULL; /* mapped dynamically in esdpci200_request_io() */
306         /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
307
308         candev->nr_82527_chips=0;
309         candev->nr_sja1000_chips=2;
310         candev->nr_all_chips=2;
311
312         return 0;
313 }
314
315 int esdpci200_init_chip_data(struct candevice_t *candev, int chipnr)
316 {
317
318         if(candev->sysdevptr.pcidev==NULL)
319                 return -ENODEV; 
320
321         CANMSG("initializing esdpci200 chip operations\n");
322
323
324         sja1000p_fill_chipspecops(candev->chip[chipnr]);
325         candev->chip[chipnr]->chip_base_addr=candev->dev_base_addr + chipnr * IO_RANGE;
326
327         candev->chip[chipnr]->chipspecops->irq_handler=esdpci200_irq_handler;
328
329         candev->chip[chipnr]->flags = 0;
330         candev->chip[chipnr]->int_cpu_reg = 0; /* i82527 specific */
331         candev->chip[chipnr]->int_clk_reg = 0; /* i82527 specific */
332         candev->chip[chipnr]->int_bus_reg = 0; /* i82527 specific */
333         candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF; /* hardware specific options for the Clock Divider register */
334         candev->chip[chipnr]->sja_ocr_reg = ESDPCI200_OCR_DEFAULT_STD; /* hardware specific options for the Output Control register */
335         candev->chip[chipnr]->clock = 16000000;
336         candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
337         candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
338         if( chipnr > 0 ) /* only one IRQ used for both channels.
339                             CHIP_IRQ_CUSTOM req'd for RTAI, since 
340                             registering two handlers for the same IRQ 
341                             returns an error */
342                 candev->chip[chipnr]->flags |= CHIP_IRQ_CUSTOM;
343
344         return 0;
345 }       
346
347 int esdpci200_init_obj_data(struct canchip_t *chip, int objnr)
348 {
349         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
350         return 0;
351 }
352
353 int esdpci200_program_irq(struct candevice_t *candev)
354 {
355
356         return 0;
357 }
358
359 int esdpci200_register(struct hwspecops_t *hwspecops)
360 {
361         hwspecops->request_io = esdpci200_request_io;
362         hwspecops->release_io = esdpci200_release_io;
363         hwspecops->reset = esdpci200_reset;
364         hwspecops->init_hw_data = esdpci200_init_hw_data;
365         hwspecops->init_chip_data = esdpci200_init_chip_data;
366         hwspecops->init_obj_data = esdpci200_init_obj_data;
367         hwspecops->write_register = esdpci200_write_register;
368         hwspecops->read_register = esdpci200_read_register;
369         hwspecops->program_irq = esdpci200_program_irq;
370         return 0;
371 }
372
373
374 #endif /*CAN_ENABLE_PCI_SUPPORT*/