]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/pccan.c
The original version of Arnaud Westenberg Linux CAN-bus driver
[lincan.git] / lincan / src / pccan.c
1 /* pccan.c
2  * Linux CAN-bus device driver.
3  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4  * This software is released under the GPL-License.
5  * Version 0.7  6 Aug 2001
6  */ 
7
8 #include <linux/autoconf.h>
9 #if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
10 #define MODVERSIONS
11 #endif
12
13 #if defined (MODVERSIONS)
14 #include <linux/modversions.h>
15 #endif
16
17 #include <linux/ioport.h>
18 #include <linux/delay.h>
19 #include <asm/irq.h>
20 #include <asm/errno.h>
21 #include <asm/io.h>
22
23 #include "../include/main.h"
24 #include "../include/pccan.h"
25 #include "../include/i82527.h"
26 #include "../include/sja1000.h"
27
28 int pccanf_request_io(unsigned long io_addr)
29 {
30         if (check_region(io_addr+0x4000,0x20)) {
31                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x4000);
32                 return -ENODEV;
33         }
34         else if (check_region(io_addr+0x6000,0x04)) {
35                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x6000);
36                 return -ENODEV;
37         }
38         else {
39                 request_region(io_addr+0x4000,0x20,DEVICE_NAME);
40                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x4000, io_addr+0x4000+0x20-1);
41                 request_region(io_addr+0x6000,0x04,DEVICE_NAME);
42                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x6000, io_addr+0x6000+0x04-1);
43         }
44         return 0;
45 }
46
47 int pccand_request_io(unsigned long io_addr)
48 {
49         if (pccanf_request_io(io_addr))
50                 return -ENODEV;
51
52         if (check_region(io_addr+0x5000,0x20)) {
53                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x5000);
54                 return -ENODEV;
55         }
56         else {
57                 request_region(io_addr+0x5000,0x20,DEVICE_NAME);
58                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x5000, io_addr+0x5000+0x20-1);
59         }
60         return 0;
61 }
62
63 int pccanq_request_io(unsigned long io_addr)
64 {
65         if (pccand_request_io(io_addr))
66                 return -ENODEV;
67
68         if (check_region(io_addr+0x2000,0x40)) {
69                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x2000);
70                 return -ENODEV;
71         }
72         else if (check_region(io_addr+0x2400,0x40)) {
73                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x2400);
74                 return -ENODEV;
75         }
76         else if (check_region(io_addr+0x2800,0x40)) {
77                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x2800);
78                 return -ENODEV;
79         }
80         else if (check_region(io_addr+0x2C00,0x40)) {
81                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x2C00);
82                 return -ENODEV;
83         }
84         else if (check_region(io_addr+0x3000,0x40)) {
85                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x3000);
86                 return -ENODEV;
87         }
88         else if (check_region(io_addr+0x3400,0x40)) {
89                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x3400);
90                 return -ENODEV;
91         }
92         else if (check_region(io_addr+0x3800,0x40)) {
93                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x3800);
94                 return -ENODEV;
95         }
96         else if (check_region(io_addr+0x3C00,0x40)) {
97                 CANMSG("Unable to open port: 0x%lx\n",io_addr+0x3C00);
98                 return -ENODEV;
99         }
100         else {
101                 request_region(io_addr+0x2000,0x40,DEVICE_NAME);
102                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x2000, io_addr+0x2000+0x40-1);
103                 request_region(io_addr+0x2400,0x40,DEVICE_NAME);
104                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x2400, io_addr+0x2400+0x40-1);
105                 request_region(io_addr+0x2800,0x40,DEVICE_NAME);
106                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x2800, io_addr+0x2800+0x40-1);
107                 request_region(io_addr+0x2C00,0x40,DEVICE_NAME);
108                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x2C00, io_addr+0x2C00+0x40-1);
109                 request_region(io_addr+0x3000,0x40,DEVICE_NAME);
110                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x3000, io_addr+0x3000+0x40-1);
111                 request_region(io_addr+0x3400,0x40,DEVICE_NAME);
112                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x3400, io_addr+0x3400+0x40-1);
113                 request_region(io_addr+0x3800,0x40,DEVICE_NAME);
114                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x3800, io_addr+0x3800+0x40-1);
115                 request_region(io_addr+0x3C00,0x40,DEVICE_NAME);
116                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr+0x3C00, io_addr+0x3C00+0x40-1);
117         }
118
119         return 0;
120 }
121
122 int pccanf_release_io(unsigned long io_addr)
123 {
124         release_region(io_addr+0x4000,0x20);
125         release_region(io_addr+0x6000,0x04);
126
127         return 0;
128 }
129
130 int pccand_release_io(unsigned long io_addr)
131 {
132         pccanf_release_io(io_addr);
133         release_region(io_addr+0x5000,0x20);
134
135         return 0;
136 }
137
138 int pccanq_release_io(unsigned long io_addr)
139 {
140         pccand_release_io(io_addr);
141         release_region(io_addr+0x2000,0x40);
142         release_region(io_addr+0x2400,0x40);
143         release_region(io_addr+0x2800,0x40);
144         release_region(io_addr+0x2C00,0x40);
145         release_region(io_addr+0x3000,0x40);
146         release_region(io_addr+0x3400,0x40);
147         release_region(io_addr+0x3800,0x40);
148         release_region(io_addr+0x3C00,0x40);
149
150         return 0;
151 }
152
153 int pccanf_reset(int card)
154 {
155         int i=0;
156
157         DEBUGMSG("Resetting pccanf/s hardware ...\n");
158         while (i < 1000000) {
159                 i++;
160                 outb(0x00,candevices_p[card]->res_addr);
161         }
162         outb(0x01,candevices_p[card]->res_addr);
163         outb(0x00,candevices_p[card]->chip[0]->chip_base_addr+SJACR);
164
165         /* Check hardware reset status */
166         i=0;
167         while ( (inb(candevices_p[card]->chip[0]->chip_base_addr+SJACR) & CR_RR)
168                                                                  && (i<=15) ) {
169                 udelay(20000);
170                 i++;
171         }
172         if (i>=15) {
173                 CANMSG("Reset status timeout!\n");
174                 CANMSG("Please check your hardware.\n");
175                 return -ENODEV;
176         }
177         else
178                 DEBUGMSG("Chip[0] reset status ok.\n");
179
180         return 0;
181 }
182
183 int pccand_reset(int card)
184 {
185         int i=0,chip_nr=0;
186
187         DEBUGMSG("Resetting pccan-d hardware ...\n");
188         while (i < 1000000) {
189                 i++;
190                 outb(0x00,candevices_p[card]->res_addr);
191         }
192         outb(0x01,candevices_p[card]->res_addr);
193         outb(0x00,candevices_p[card]->chip[0]->chip_base_addr+SJACR);
194         outb(0x00,candevices_p[card]->chip[1]->chip_base_addr+SJACR);
195
196         /* Check hardware reset status */
197         i=0;
198         for (chip_nr=0; chip_nr<2; chip_nr++) {
199                 i=0;
200                 while ( (inb(candevices_p[card]->chip[chip_nr]->chip_base_addr +
201                                                 SJACR) & CR_RR) && (i<=15) ) {
202                         udelay(20000);
203                         i++;
204                 }
205                 if (i>=15) {
206                         CANMSG("Reset status timeout!\n");
207                         CANMSG("Please check your hardware.\n");
208                         return -ENODEV;
209                 }
210                 else
211                         DEBUGMSG("Chip%d reset status ok.\n",chip_nr);
212         }
213         return 0;
214 }
215
216 int pccanq_reset(int card)
217 {
218         int i=0,chip_nr=0;
219
220         for (i=0; i<4; i++)
221                 disable_irq(candevices_p[card]->chip[i]->chip_irq);
222
223         DEBUGMSG("Resetting pccan-q hardware ...\n");
224         while (i < 100000) {
225                 i++;
226                 outb(0x00,candevices_p[card]->res_addr);
227         }
228         outb_p(0x01,candevices_p[card]->res_addr);
229                 
230         outb(0x00,candevices_p[card]->chip[2]->chip_base_addr+SJACR);
231         outb(0x00,candevices_p[card]->chip[3]->chip_base_addr+SJACR);
232
233         /* Check hardware reset status */
234         for (chip_nr=0; chip_nr<2; chip_nr++) {
235                 i=0;
236                 while( (inb(candevices_p[card]->chip[chip_nr]->chip_base_addr +
237                                                 iCPU) & iCPU_RST) && (i<=15) ) {
238                         udelay(20000);
239                         i++;
240                 }
241                 if (i>=15) {
242                         CANMSG("Reset status timeout!\n");
243                         CANMSG("Please check your hardware.\n");
244                         return -ENODEV;
245                 }
246                 else 
247                         DEBUGMSG("Chip%d reset status ok.\n",chip_nr);
248         }
249         for (chip_nr=2; chip_nr<4; chip_nr++) {
250                 i=0;
251                 while( (inb(candevices_p[card]->chip[chip_nr]->chip_base_addr +
252                                                 SJACR) & CR_RR) && (i<=15) ) {
253                         udelay(20000);
254                         i++;
255                 }
256                 if (i>=15) {
257                         CANMSG("Reset status timeout!\n");
258                         CANMSG("Please check your hardware.\n");
259                         return -ENODEV;
260                 }
261                 else
262                         DEBUGMSG("Chip%d reset status ok.\n",chip_nr);
263         }
264
265         for (i=0; i<4; i++)
266                 enable_irq(candevices_p[card]->chip[i]->chip_irq);
267
268         return 0;
269 }       
270
271 int pccan_init_hw_data(int card)
272 {
273         candevices_p[card]->res_addr=candevices_p[card]->io_addr+0x6001;
274         candevices_p[card]->flags |= PROGRAMMABLE_IRQ;
275
276         if (!strcmp(candevices_p[card]->hwname,"pccan-q")) {
277                 candevices_p[card]->nr_82527_chips=2;
278                 candevices_p[card]->nr_sja1000_chips=2;
279         }
280         if (!strcmp(candevices_p[card]->hwname,"pccan-f") |
281             !strcmp(candevices_p[card]->hwname,"pccan-s")) {
282                 candevices_p[card]->nr_82527_chips=0;
283                 candevices_p[card]->nr_sja1000_chips=1;
284         }
285         if (!strcmp(candevices_p[card]->hwname,"pccan-d")) {
286                 candevices_p[card]->nr_82527_chips=0;
287                 candevices_p[card]->nr_sja1000_chips=2;
288         }
289
290         return 0;
291 }
292
293 int pccan_init_chip_data(int card, int chipnr)
294 {
295         if (!strcmp(candevices_p[card]->hwname,"pccan-q")) {
296                 if (chipnr<2) {
297                         candevices_p[card]->chip[chipnr]->chip_type="i82527";
298                         candevices_p[card]->chip[chipnr]->flags = SEGMENTED;
299                         candevices_p[card]->chip[chipnr]->int_cpu_reg=iCPU_DSC;
300                         candevices_p[card]->chip[chipnr]->int_clk_reg=iCLK_SL1;
301                         candevices_p[card]->chip[chipnr]->int_bus_reg=iBUS_CBY;
302                         candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0;
303                         candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0;      
304                 }
305                 else{
306                         candevices_p[card]->chip[chipnr]->chip_type="sja1000";
307                         candevices_p[card]->chip[chipnr]->flags = 0;
308                         candevices_p[card]->chip[chipnr]->int_cpu_reg = 0;
309                         candevices_p[card]->chip[chipnr]->int_clk_reg = 0;
310                         candevices_p[card]->chip[chipnr]->int_bus_reg = 0;
311                         candevices_p[card]->chip[chipnr]->sja_cdr_reg =
312                                                                 CDR_CLK_OFF;
313                         candevices_p[card]->chip[chipnr]->sja_ocr_reg = 
314                                                 OCR_MODE_NORMAL | OCR_TX0_LH;   
315                 }
316                 candevices_p[card]->chip[chipnr]->chip_base_addr=0x1000*chipnr+0x2000+candevices_p[card]->io_addr;
317         }
318         else {
319                 candevices_p[card]->chip[chipnr]->chip_type="sja1000";
320                 candevices_p[card]->chip[chipnr]->chip_base_addr=0x1000*chipnr+0x4000+candevices_p[card]->io_addr;
321                 candevices_p[card]->chip[chipnr]->flags = 0;
322                 candevices_p[card]->chip[chipnr]->int_cpu_reg = 0;
323                 candevices_p[card]->chip[chipnr]->int_clk_reg = 0;
324                 candevices_p[card]->chip[chipnr]->int_bus_reg = 0;
325                 candevices_p[card]->chip[chipnr]->sja_cdr_reg = CDR_CLK_OFF;
326                 candevices_p[card]->chip[chipnr]->sja_ocr_reg = 
327                                                 OCR_MODE_NORMAL | OCR_TX0_LH;   
328         }
329
330         candevices_p[card]->chip[chipnr]->clock = 16000000;
331
332         return 0;
333 }       
334
335 int pccan_init_obj_data(int chipnr, int objnr)
336 {
337         if (!strcmp(chips_p[chipnr]->chip_type,"sja1000")) {
338                 chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr;
339                 chips_p[chipnr]->msgobj[objnr]->flags=0;
340         }
341         else {
342                 chips_p[chipnr]->msgobj[objnr]->obj_base_addr=chips_p[chipnr]->chip_base_addr+(objnr+1)*0x10+(int)((objnr+1)/4)*0x3c0;
343                 chips_p[chipnr]->msgobj[objnr]->flags=0;
344         }
345
346         return 0;
347 }
348
349 int pccan_program_irq(int card)
350 {
351         #define IRQ9 0x01
352         #define IRQ3 0x02
353         #define IRQ5 0x03
354
355         unsigned char irq_reg_value=0;
356         int i;
357
358         for (i=0; i<4; i++) {
359                 switch (candevices_p[card]->chip[i]->chip_irq) {
360                         case 0: {
361                                 break;
362                         }
363                         case 3: {
364                                 irq_reg_value |= (IRQ3<<(i*2));
365                                 break;
366                         }
367                         case 5: {
368                                 irq_reg_value |= (IRQ5<<(i*2));
369                                 break;
370                         }
371                         case 9: {
372                                 irq_reg_value |= (IRQ9<<(i*2));
373                                 break;
374                         }
375                         default: {
376                                 CANMSG("Supplied interrupt is not supported by the hardware\n");
377                                 return -ENODEV;
378                         }
379                 }
380         }
381         outb(irq_reg_value,0x6000+candevices_p[card]->io_addr);
382         DEBUGMSG("Configured pccan hardware interrupts\n");
383         outb(0x80,0x6000+candevices_p[card]->io_addr+0x02);
384         DEBUGMSG("Selected pccan on-board 16 MHz oscillator\n");
385
386         return 0;
387 }
388
389 inline void pccan_write_register(unsigned char data, unsigned long address)
390 {
391         outb(data,address); 
392 }
393
394 unsigned pccan_read_register(unsigned long address)
395 {
396         return inb(address);
397 }
398
399 int pccanf_register(struct hwspecops_t *hwspecops)
400 {
401         hwspecops->request_io = pccanf_request_io;
402         hwspecops->release_io = pccanf_release_io;
403         hwspecops->reset = pccanf_reset;
404         hwspecops->init_hw_data = pccan_init_hw_data;
405         hwspecops->init_chip_data = pccan_init_chip_data;
406         hwspecops->init_obj_data = pccan_init_obj_data;
407         hwspecops->write_register = pccan_write_register;
408         hwspecops->read_register = pccan_read_register;
409         hwspecops->program_irq = pccan_program_irq;
410         return 0;
411 }
412
413
414 int pccand_register(struct hwspecops_t *hwspecops)
415 {
416         hwspecops->request_io = pccand_request_io;
417         hwspecops->release_io = pccand_release_io;
418         hwspecops->reset = pccand_reset;
419         hwspecops->init_hw_data = pccan_init_hw_data;
420         hwspecops->init_chip_data = pccan_init_chip_data;
421         hwspecops->init_obj_data = pccan_init_obj_data;
422         hwspecops->write_register = pccan_write_register;
423         hwspecops->read_register = pccan_read_register;
424         hwspecops->program_irq = pccan_program_irq;
425         return 0;
426 }
427
428
429 int pccanq_register(struct hwspecops_t *hwspecops)
430 {
431         hwspecops->request_io = pccanq_request_io;
432         hwspecops->release_io = pccanq_release_io;
433         hwspecops->reset = pccanq_reset;
434         hwspecops->init_hw_data = pccan_init_hw_data;
435         hwspecops->init_chip_data = pccan_init_chip_data;
436         hwspecops->init_obj_data = pccan_init_obj_data;
437         hwspecops->write_register = pccan_write_register;
438         hwspecops->read_register = pccan_read_register;
439         hwspecops->program_irq = pccan_program_irq;
440         return 0;
441 }