1 /**************************************************************************/
2 /* File: kv_pcican.c - support for KVASER PCIcan-S/D/Q cards */
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 /* Funded by OCERA and FRESCOR IST projects */
8 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl> */
10 /* LinCAN is free software; you can redistribute it and/or modify it */
11 /* under terms of the GNU General Public License as published by the */
12 /* Free Software Foundation; either version 2, or (at your option) any */
13 /* later version. LinCAN is distributed in the hope that it will be */
14 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
15 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
16 /* General Public License for more details. You should have received a */
17 /* copy of the GNU General Public License along with LinCAN; see file */
18 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
19 /* Cambridge, MA 02139, USA. */
21 /* To allow use of LinCAN in the compact embedded systems firmware */
22 /* and RT-executives (RTEMS for example), main authors agree with next */
23 /* special exception: */
25 /* Including LinCAN header files in a file, instantiating LinCAN generics */
26 /* or templates, or linking other files with LinCAN objects to produce */
27 /* an application image/executable, does not by itself cause the */
28 /* resulting application image/executable to be covered by */
29 /* the GNU General Public License. */
30 /* This exception does not however invalidate any other reasons */
31 /* why the executable file might be covered by the GNU Public License. */
32 /* Publication of enhanced or derived LinCAN files is required although. */
33 /**************************************************************************/
35 #include "../include/can.h"
36 #include "../include/can_sysdep.h"
37 #include "../include/main.h"
38 #include "../include/sja1000p.h"
40 #ifdef CAN_ENABLE_PCI_SUPPORT
42 #define KV_PCICAN_PCICAN_VENDOR 0x10e8
43 #define KV_PCICAN_PCICAN_ID 0x8406
47 #define S5920_OMB 0x0C
48 #define S5920_IMB 0x1C
49 #define S5920_MBEF 0x34
50 #define S5920_INTCSR 0x38
51 #define S5920_RCR 0x3C
52 #define S5920_PTCR 0x60
54 #define INTCSR_ADDON_INTENABLE_M 0x2000
55 #define INTCSR_INTERRUPT_ASSERTED_M 0x800000
57 #define KV_PCICAN_BYTES_PER_CIRCUIT 0x20
59 // Standard value: Pushpull (OCTP1|OCTN1|OCTP0|OCTN0|OCM1)
60 #define KV_PCICAN_OCR_DEFAULT_STD 0xDA
61 // For Galathea piggyback.
62 #define KV_PCICAN_OCR_DEFAULT_GAL 0xDB
66 You need to know the following:
67 " RX1 is connected to ground.
68 " TX1 is not connected.
69 " CLKO is not connected.
70 " Setting the OCR register to 0xDA is a good idea.
71 This means normal output mode , push-pull and the correct polarity.
72 " In the CDR register, you should set CBP to 1.
73 You will probably also want to set the clock divider value to 0 (meaning divide-by-2),
74 the Pelican bit, and the clock-off bit (you have no need for CLKOUT anyway.)
80 void kv_pcican_disconnect_irq(struct candevice_t *candev)
83 /* Disable interrupts from card */
84 tmp = can_inl(candev->dev_base_addr + S5920_INTCSR);
85 tmp &= ~INTCSR_ADDON_INTENABLE_M;
86 can_outl(tmp, candev->dev_base_addr + S5920_INTCSR);
89 void kv_pcican_connect_irq(struct candevice_t *candev)
92 /* Enable interrupts from card */
93 tmp = can_inl(candev->dev_base_addr + S5920_INTCSR);
94 tmp |= INTCSR_ADDON_INTENABLE_M;
95 can_outl(tmp, candev->dev_base_addr + S5920_INTCSR);
99 int kv_pcican_request_io(struct candevice_t *candev)
101 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
102 if(pci_request_region(candev->sysdevptr.pcidev, 0, "kv_pcican_s5920") != 0){
103 CANMSG("Request of kv_pcican_s5920 range failed\n");
105 }else if(pci_request_region(candev->sysdevptr.pcidev, 1, "kv_pcican_io") != 0){
106 CANMSG("Request of kv_pcican_io range failed\n");
108 }else if(pci_request_region(candev->sysdevptr.pcidev, 2, "kv_pcican_xilinx") != 0){
109 CANMSG("Request of kv_pcican_xilinx range failed\n");
112 #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
113 if(pci_request_regions(candev->sysdevptr.pcidev, "kv_pcican") != 0){
114 CANMSG("Request of kv_pcican_s5920 regions failed\n");
117 #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
119 kv_pcican_disconnect_irq(candev);
123 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
125 pci_release_region(candev->sysdevptr.pcidev, 1);
127 pci_release_region(candev->sysdevptr.pcidev, 0);
128 #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
133 int kv_pcican_release_io(struct candevice_t *candev)
135 kv_pcican_disconnect_irq(candev);
137 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
138 pci_release_region(candev->sysdevptr.pcidev, 2);
139 pci_release_region(candev->sysdevptr.pcidev, 1);
140 pci_release_region(candev->sysdevptr.pcidev, 0);
141 #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
142 pci_release_regions(candev->sysdevptr.pcidev);
143 #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
149 void kv_pcican_write_register(unsigned data, can_ioptr_t address)
151 can_outb(data,address);
154 unsigned kv_pcican_read_register(can_ioptr_t address)
156 return can_inb(address);
159 int kv_pcican_reset(struct candevice_t *candev)
162 struct canchip_t *chip;
165 DEBUGMSG("Resetting kv_pcican hardware ...\n");
167 /* Assert PTADR# - we're in passive mode so the other bits are not important */
168 can_outl(0x80808080L, candev->dev_base_addr + S5920_PTCR);
170 kv_pcican_disconnect_irq(candev);
172 for(chip_nr=0;chip_nr<candev->nr_all_chips;chip_nr++){
173 if(!candev->chip[chip_nr]) continue;
174 chip=candev->chip[chip_nr];
176 kv_pcican_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
179 cdr=kv_pcican_read_register(chip->chip_base_addr+SJACDR);
180 kv_pcican_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
182 kv_pcican_write_register(0, chip->chip_base_addr+SJAIER);
185 kv_pcican_write_register(0, chip->chip_base_addr+SJAMOD);
186 while (kv_pcican_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
187 if(!i--) return -ENODEV;
189 kv_pcican_write_register(0, chip->chip_base_addr+SJAMOD);
192 cdr=kv_pcican_read_register(chip->chip_base_addr+SJACDR);
193 kv_pcican_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
195 kv_pcican_write_register(0, chip->chip_base_addr+SJAIER);
197 kv_pcican_read_register(chip->chip_base_addr+SJAIR);
201 kv_pcican_connect_irq(candev);
206 int kv_pcican_init_hw_data(struct candevice_t *candev)
208 struct pci_dev *pcidev = NULL;
212 pcidev = pci_find_device(KV_PCICAN_PCICAN_VENDOR, KV_PCICAN_PCICAN_ID, pcidev);
213 if(pcidev == NULL) return -ENODEV;
214 } while(can_check_dev_taken(pcidev));
216 if (pci_enable_device (pcidev)){
217 printk(KERN_CRIT "Setup of PCICAN failed\n");
220 candev->sysdevptr.pcidev=pcidev;
223 if(!(pci_resource_flags(pcidev,i)&IORESOURCE_IO)){
224 printk(KERN_CRIT "PCICAN region %d is not IO\n",i);
228 candev->dev_base_addr=pci_resource_start(pcidev,0); /*S5920*/
229 candev->io_addr=pci_resource_start(pcidev,1); /*IO window for SJA1000 chips*/
230 candev->res_addr=pci_resource_start(pcidev,2); /*XILINX board wide address*/
232 /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
234 if (!strcmp(candev->hwname,"pcican-s")) {
235 candev->nr_82527_chips=0;
236 candev->nr_sja1000_chips=1;
237 candev->nr_all_chips=1;
239 if (!strcmp(candev->hwname,"pcican-d")) {
240 candev->nr_82527_chips=0;
241 candev->nr_sja1000_chips=2;
242 candev->nr_all_chips=2;
244 if (!strcmp(candev->hwname,"pcican-q")) {
245 candev->nr_82527_chips=0;
246 candev->nr_sja1000_chips=4;
247 candev->nr_all_chips=4;
253 int kv_pcican_init_chip_data(struct candevice_t *candev, int chipnr)
256 if(candev->sysdevptr.pcidev==NULL)
259 candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
261 sja1000p_fill_chipspecops(candev->chip[chipnr]);
262 candev->chip[chipnr]->chip_base_addr=
263 candev->io_addr+chipnr*KV_PCICAN_BYTES_PER_CIRCUIT;
264 candev->chip[chipnr]->flags = 0;
265 candev->chip[chipnr]->int_cpu_reg = 0;
266 candev->chip[chipnr]->int_clk_reg = 0;
267 candev->chip[chipnr]->int_bus_reg = 0;
268 candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
269 candev->chip[chipnr]->sja_ocr_reg = KV_PCICAN_OCR_DEFAULT_STD;
270 candev->chip[chipnr]->clock = 16000000;
271 candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
276 int kv_pcican_init_obj_data(struct canchip_t *chip, int objnr)
278 chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
282 int kv_pcican_program_irq(struct candevice_t *candev)
288 int kv_pcican_register(struct hwspecops_t *hwspecops)
290 hwspecops->request_io = kv_pcican_request_io;
291 hwspecops->release_io = kv_pcican_release_io;
292 hwspecops->reset = kv_pcican_reset;
293 hwspecops->init_hw_data = kv_pcican_init_hw_data;
294 hwspecops->init_chip_data = kv_pcican_init_chip_data;
295 hwspecops->init_obj_data = kv_pcican_init_obj_data;
296 hwspecops->write_register = kv_pcican_write_register;
297 hwspecops->read_register = kv_pcican_read_register;
298 hwspecops->program_irq = kv_pcican_program_irq;
303 #endif /*CAN_ENABLE_PCI_SUPPORT*/