1 /**************************************************************************/
2 /* File: pcisja1000mm.c - SJA1000 directly mapped into PCI mem region 0 */
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 DIRECT_PCISJA100_VENDOR 0x1b36
43 #define DIRECT_PCISJA100_ID 0xbeef
45 #define PCISJA1000MM_OCR_DEFAULT_STD 0xDA
47 #define PCISJA1000MM_BYTES_PER_CIRCUIT 0x80
49 void pcisja1000mm_disconnect_irq(struct candevice_t *candev)
53 void pcisja1000mm_connect_irq(struct candevice_t *candev)
57 int pcisja1000mm_request_io(struct candevice_t *candev)
59 unsigned long io_addr;
62 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
63 if(pci_request_region(candev->sysdevptr.pcidev, 0, "pcisja1000mm") != 0){
64 CANMSG("Request of pcisja1000mm range failed\n");
67 #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
68 if(pci_request_regions(candev->sysdevptr.pcidev, "pcisja1000mm") != 0){
69 CANMSG("Request of pcisja1000mm regions failed\n");
72 #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
74 io_addr=pci_resource_start(candev->sysdevptr.pcidev,0);;
75 if (!(candev->dev_base_addr = ioremap(io_addr,
76 pci_resource_len(candev->sysdevptr.pcidev,0)))) {
77 CANMSG("Unable to access I/O memory at: 0x%lx\n", io_addr);
78 goto error_ioremap_io;
81 candev->io_addr=io_addr;
84 * this is redundant with chip initialization, but remap address
85 * can change when resources are temporarily released
87 for(i=0;i<candev->nr_all_chips;i++) {
88 struct canchip_t *chip=candev->chip[i];
90 chip->chip_base_addr = candev->dev_base_addr +
91 i * PCISJA1000MM_BYTES_PER_CIRCUIT;
92 if(!chip->msgobj[0]) continue;
93 chip->msgobj[0]->obj_base_addr=chip->chip_base_addr;
96 pcisja1000mm_disconnect_irq(candev);
101 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
102 pci_release_region(candev->sysdevptr.pcidev, 0);
103 #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
104 pci_release_regions(candev->sysdevptr.pcidev);
105 #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
109 int pcisja1000mm_release_io(struct candevice_t *candev)
111 pcisja1000mm_disconnect_irq(candev);
113 iounmap(candev->dev_base_addr);
115 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
116 pci_release_region(candev->sysdevptr.pcidev, 0);
117 #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
118 pci_release_regions(candev->sysdevptr.pcidev);
119 #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
125 void pcisja1000mm_write_register(unsigned data, can_ioptr_t address)
127 can_writeb(data,address);
130 unsigned pcisja1000mm_read_register(can_ioptr_t address)
132 return can_readb(address);
135 int pcisja1000mm_reset(struct candevice_t *candev)
138 struct canchip_t *chip;
141 DEBUGMSG("Resetting pcisja1000mm hardware ...\n");
143 pcisja1000mm_disconnect_irq(candev);
145 for(chip_nr=0;chip_nr<candev->nr_all_chips;chip_nr++){
146 if(!candev->chip[chip_nr]) continue;
147 chip=candev->chip[chip_nr];
149 pcisja1000mm_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
152 cdr=pcisja1000mm_read_register(chip->chip_base_addr+SJACDR);
153 pcisja1000mm_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
155 pcisja1000mm_write_register(0, chip->chip_base_addr+SJAIER);
158 pcisja1000mm_write_register(0, chip->chip_base_addr+SJAMOD);
159 while (pcisja1000mm_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
160 if(!i--) return -ENODEV;
162 pcisja1000mm_write_register(0, chip->chip_base_addr+SJAMOD);
165 cdr=pcisja1000mm_read_register(chip->chip_base_addr+SJACDR);
166 pcisja1000mm_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
168 pcisja1000mm_write_register(0, chip->chip_base_addr+SJAIER);
170 pcisja1000mm_read_register(chip->chip_base_addr+SJAIR);
174 pcisja1000mm_connect_irq(candev);
179 int pcisja1000mm_init_hw_data(struct candevice_t *candev)
181 struct pci_dev *pcidev;
184 pcidev = can_pci_get_next_untaken_device(DIRECT_PCISJA100_VENDOR, DIRECT_PCISJA100_ID);
188 if (pci_enable_device (pcidev)){
189 printk(KERN_CRIT "Setup of PCISJA1000MM failed\n");
190 can_pci_dev_put(pcidev);
193 candev->sysdevptr.pcidev=pcidev;
197 if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
198 printk(KERN_ERR "PCISJA1000MM region %d is not memory\n",i);
202 candev->io_addr=pci_resource_start(pcidev,0); /*IO window for SJA1000 chips*/
203 candev->dev_base_addr=can_ulong2ioptr(candev->io_addr);
206 /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
208 candev->nr_82527_chips=0;
209 candev->nr_sja1000_chips=1;
210 candev->nr_all_chips=1;
216 printk(KERN_CRIT "Setup of PCISJA1000MM failed\n");
217 pci_disable_device (pcidev);
218 can_pci_dev_put(pcidev);
222 void pcisja1000mm_done_hw_data(struct candevice_t *candev)
224 struct pci_dev *pcidev = candev->sysdevptr.pcidev;
225 can_pci_dev_put(pcidev);
228 int pcisja1000mm_init_chip_data(struct candevice_t *candev, int chipnr)
231 if(candev->sysdevptr.pcidev==NULL)
234 candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
236 sja1000p_fill_chipspecops(candev->chip[chipnr]);
237 candev->chip[chipnr]->chip_base_addr=
238 can_ioport2ioptr(candev->io_addr+chipnr*PCISJA1000MM_BYTES_PER_CIRCUIT);
240 candev->chip[chipnr]->flags = 0;
241 candev->chip[chipnr]->int_cpu_reg = 0;
242 candev->chip[chipnr]->int_clk_reg = 0;
243 candev->chip[chipnr]->int_bus_reg = 0;
244 candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
245 candev->chip[chipnr]->sja_ocr_reg = PCISJA1000MM_OCR_DEFAULT_STD;
246 candev->chip[chipnr]->clock = 16000000;
247 candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
252 int pcisja1000mm_init_obj_data(struct canchip_t *chip, int objnr)
254 chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
258 int pcisja1000mm_program_irq(struct candevice_t *candev)
264 int pcisja1000mm_register(struct hwspecops_t *hwspecops)
266 hwspecops->request_io = pcisja1000mm_request_io;
267 hwspecops->release_io = pcisja1000mm_release_io;
268 hwspecops->reset = pcisja1000mm_reset;
269 hwspecops->init_hw_data = pcisja1000mm_init_hw_data;
270 hwspecops->done_hw_data = pcisja1000mm_done_hw_data;
271 hwspecops->init_chip_data = pcisja1000mm_init_chip_data;
272 hwspecops->init_obj_data = pcisja1000mm_init_obj_data;
273 hwspecops->write_register = pcisja1000mm_write_register;
274 hwspecops->read_register = pcisja1000mm_read_register;
275 hwspecops->program_irq = pcisja1000mm_program_irq;
280 #endif /*CAN_ENABLE_PCI_SUPPORT*/