]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/adlink7841.c
changed usb vendor and product id.
[lincan.git] / lincan / src / adlink7841.c
1 /* adlink7841.c - support for ADLINK 7841 cards
2  * Linux CAN-bus device driver.
3  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4  * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
5  * email:pisa@cmp.felk.cvut.cz
6  * This software is released under the GPL-License.
7  * Version lincan-0.3  17 Jun 2004
8  */ 
9
10 #include "../include/can.h"
11 #include "../include/can_sysdep.h"
12 #include "../include/main.h"
13 #include "../include/sja1000p.h"
14
15 #ifdef CAN_ENABLE_PCI_SUPPORT
16
17 #define ADLINK7841_PCI_VENDOR_ID        0x144A  /* ADLINK vednor id */
18 #define ADLINK7841_PCI_PRODUCT_ID       0x7841  /* PCI 7841 device ID */
19
20 /* PCI to local bus bridge PLX9050 */
21
22 #define PLX9050_INTCSR  0x4c    /* interrupt control register */
23
24 #define ADLINK7841_BYTES_PER_CIRCUIT 0x80
25
26 // Standard value: Pushpull  (OCTP1|OCTN1|OCPOL1|OCTP0|OCTN0|OCM1)
27 #define ADLINK7841_OCR_DEFAULT_STD 0xFA
28
29 /*
30
31 You need to know the following: 
32 " RX1 is connected to ground. 
33 " TX1 is not connected. 
34 " CLKO is not connected. 
35 " Setting the OCR register to 0xFA is a good idea. 
36   This means  normal output mode , push-pull and the correct polarity. 
37 " In the CDR register, you should set CBP to 1. 
38   You will probably also want to set the clock divider value to 0 (meaning divide-by-2),
39   the Pelican bit, and the clock-off bit (you have no need for CLKOUT anyway.)
40
41 */
42
43
44
45 void adlink7841_disconnect_irq(struct candevice_t *candev)
46 {
47 }
48
49 void adlink7841_connect_irq(struct candevice_t *candev)
50 {
51 }
52
53
54 int adlink7841_request_io(struct candevice_t *candev)
55 {
56     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
57         if(pci_request_region(candev->sysdevptr.pcidev, 1, "adlink7841_plx9050") != 0){
58                 CANMSG("Request of adlink7841_plx9050 range failed\n");
59                 return -ENODEV;
60         }else if(pci_request_region(candev->sysdevptr.pcidev, 2, "adlink7841_io") != 0){
61                 CANMSG("Request of adlink7841_io range failed\n");
62                 goto error_io;
63         }
64     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
65         if(pci_request_regions(candev->sysdevptr.pcidev, "adlink7841") != 0){
66                 CANMSG("Request of adlink7841_plx9050 regions failed\n");
67                 return -ENODEV;
68         }
69     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
70
71         adlink7841_disconnect_irq(candev);
72
73         return 0;
74
75     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
76     error_io:
77         pci_release_region(candev->sysdevptr.pcidev, 1);
78     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
79         
80         return -ENODEV;
81 }
82
83 int adlink7841_release_io(struct candevice_t *candev)
84 {
85         adlink7841_disconnect_irq(candev);
86
87     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
88         pci_release_region(candev->sysdevptr.pcidev, 2);
89         pci_release_region(candev->sysdevptr.pcidev, 1);
90     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
91         pci_release_regions(candev->sysdevptr.pcidev);
92     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
93
94         return 0;
95 }
96
97
98 void adlink7841_write_register(unsigned data, unsigned long address)
99 {
100         outb(data,address); 
101 }
102
103 unsigned adlink7841_read_register(unsigned long address)
104 {
105         return inb(address);
106 }
107
108 int adlink7841_reset(struct candevice_t *candev)
109 {
110         int i=0,chip_nr;
111         struct canchip_t *chip;
112         unsigned cdr;
113
114         DEBUGMSG("Resetting adlink7841 hardware ...\n");
115
116         adlink7841_disconnect_irq(candev);
117
118         for(chip_nr=0;chip_nr<candev->nr_all_chips;chip_nr++){
119                 if(!candev->chip[chip_nr]) continue;
120                 chip=candev->chip[chip_nr];
121
122                 adlink7841_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
123                 udelay(1000);
124
125                 cdr=adlink7841_read_register(chip->chip_base_addr+SJACDR);
126                 adlink7841_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
127
128                 adlink7841_write_register(0, chip->chip_base_addr+SJAIER);
129
130                 i=20;
131                 adlink7841_write_register(0, chip->chip_base_addr+SJAMOD);
132                 while (adlink7841_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM){
133                         if(!i--) return -ENODEV;
134                         udelay(1000);
135                         adlink7841_write_register(0, chip->chip_base_addr+SJAMOD);
136                 }
137
138                 cdr=adlink7841_read_register(chip->chip_base_addr+SJACDR);
139                 adlink7841_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
140
141                 adlink7841_write_register(0, chip->chip_base_addr+SJAIER);
142                 
143                 adlink7841_read_register(chip->chip_base_addr+SJAIR);
144         }
145         
146
147         adlink7841_connect_irq(candev);
148
149         return 0;
150 }       
151
152 int adlink7841_init_hw_data(struct candevice_t *candev)
153 {
154         struct pci_dev *pcidev = NULL;
155         int i;
156
157         do {
158                 pcidev = pci_find_device(ADLINK7841_PCI_VENDOR_ID, ADLINK7841_PCI_PRODUCT_ID, pcidev);
159                 if(pcidev == NULL) return -ENODEV;
160         } while(can_check_dev_taken(pcidev));
161         
162         if (pci_enable_device (pcidev)){
163                 printk(KERN_CRIT "Setup of ADLINK7841 failed\n");
164                 return -EIO;
165         }
166         candev->sysdevptr.pcidev=pcidev;
167         
168         for(i=1;i<3;i++){
169                 if(!(pci_resource_flags(pcidev,i)&IORESOURCE_IO)){
170                         printk(KERN_CRIT "ADLINK7841 region %d is not IO\n",i);
171                         return -EIO;
172                 }
173         }
174         candev->dev_base_addr=pci_resource_start(pcidev,1); /* PLX 9050 BASE*/
175         candev->io_addr=pci_resource_start(pcidev,2); /*IO window for SJA1000 chips*/
176         candev->res_addr=pci_resource_start(pcidev,1); /*reserved*/
177         
178         /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
179
180         candev->nr_82527_chips=0;
181         candev->nr_sja1000_chips=2;
182         candev->nr_all_chips=2;
183
184         return 0;
185 }
186
187 int adlink7841_init_chip_data(struct candevice_t *candev, int chipnr)
188 {
189
190         if(candev->sysdevptr.pcidev==NULL)
191                 return -ENODEV;
192         
193         candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
194
195         sja1000p_fill_chipspecops(candev->chip[chipnr]);
196         candev->chip[chipnr]->chip_base_addr=
197                         candev->io_addr+chipnr*ADLINK7841_BYTES_PER_CIRCUIT;
198         candev->chip[chipnr]->flags = 0;
199         candev->chip[chipnr]->int_cpu_reg = 0;
200         candev->chip[chipnr]->int_clk_reg = 0;
201         candev->chip[chipnr]->int_bus_reg = 0;
202         candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
203         candev->chip[chipnr]->sja_ocr_reg = ADLINK7841_OCR_DEFAULT_STD;
204         candev->chip[chipnr]->clock = 16000000;
205         candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
206
207         return 0;
208 }       
209
210 int adlink7841_init_obj_data(struct canchip_t *chip, int objnr)
211 {
212         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
213         return 0;
214 }
215
216 int adlink7841_program_irq(struct candevice_t *candev)
217 {
218
219         return 0;
220 }
221
222 int adlink7841_register(struct hwspecops_t *hwspecops)
223 {
224         hwspecops->request_io = adlink7841_request_io;
225         hwspecops->release_io = adlink7841_release_io;
226         hwspecops->reset = adlink7841_reset;
227         hwspecops->init_hw_data = adlink7841_init_hw_data;
228         hwspecops->init_chip_data = adlink7841_init_chip_data;
229         hwspecops->init_obj_data = adlink7841_init_obj_data;
230         hwspecops->write_register = adlink7841_write_register;
231         hwspecops->read_register = adlink7841_read_register;
232         hwspecops->program_irq = adlink7841_program_irq;
233         return 0;
234 }
235
236
237 #endif /*CAN_ENABLE_PCI_SUPPORT*/