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