]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/smartcan.c
The original version of Arnaud Westenberg Linux CAN-bus driver
[lincan.git] / lincan / src / smartcan.c
1 /* smartcan.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 <linux/sched.h>
20 #include <asm/errno.h>
21 #include <asm/io.h>
22 #include <asm/irq.h>
23
24 #include "../include/main.h"
25 #include "../include/smartcan.h"
26 #include "../include/i82527.h"
27
28 int smartcan_irq=-1;
29 unsigned long smartcan_base=0x0;
30
31 int smartcan_request_io(unsigned long io_addr)
32 {
33         int err=0;
34
35         if ( (err=check_region(io_addr,0x04)) < 0 ) {
36                 CANMSG("Unable to open port: 0x%lx\n",io_addr);
37                 return -ENODEV;
38         }
39         else {
40                 request_region(io_addr,0x04,DEVICE_NAME);
41                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", io_addr, io_addr + 0x04 - 1);
42         }
43         return 0;
44 }
45
46 int smartcan_release_io(unsigned long io_addr)
47 {
48         release_region(io_addr,0x04);
49
50         return 0;
51 }
52
53 int smartcan_reset(int card)
54 {
55         int i=0;
56
57         DEBUGMSG("Resetting smartcan hardware ...\n");
58         outb(0x00,candevices_p[card]->res_addr);
59         while (i < 1000000) {
60                 i++;
61                 outb(0x01,candevices_p[card]->res_addr);
62         }
63         outb(0x00,candevices_p[card]->res_addr); 
64
65         /* Check hardware reset status */
66         i=0;
67         outb(candevices_p[card]->io_addr+iCPU,candevices_p[card]->io_addr);
68         while ( (inb(candevices_p[card]->io_addr+1)&0x80) && (i<=15) ) {
69                 udelay(20000);
70                 i++;
71         }
72         if (i>=15) {
73                 CANMSG("Reset status timeout!\n");
74                 CANMSG("Please check your hardware.\n");
75                 return -ENODEV;
76         }
77         else
78                 DEBUGMSG("Chip0 reset status ok.\n");
79
80         return 0;
81
82
83 int smartcan_init_hw_data(int card)
84 {
85         candevices_p[card]->res_addr=candevices_p[card]->io_addr+0x02;
86         candevices_p[card]->nr_82527_chips=1;
87         candevices_p[card]->nr_sja1000_chips=0;
88
89         return 0;
90 }
91
92 int smartcan_init_chip_data(int card, int chipnr)
93 {
94         candevices_p[card]->chip[chipnr]->chip_type="i82527";
95         candevices_p[card]->chip[chipnr]->chip_base_addr=candevices_p[card]->io_addr;
96         candevices_p[card]->chip[chipnr]->clock = 16000000;
97         candevices_p[card]->chip[chipnr]->int_cpu_reg = iCPU_DSC;
98         candevices_p[card]->chip[chipnr]->int_clk_reg = iCLK_SL1;
99         candevices_p[card]->chip[chipnr]->int_bus_reg = iBUS_CBY;
100         candevices_p[card]->chip[chipnr]->sja_cdr_reg = 0;
101         candevices_p[card]->chip[chipnr]->sja_ocr_reg = 0;
102         smartcan_irq=candevices_p[card]->chip[chipnr]->chip_irq;
103         smartcan_base=candevices_p[card]->chip[chipnr]->chip_base_addr;
104
105         return 0;
106 }
107
108 int smartcan_init_obj_data(int chipnr, int objnr)
109 {
110         chips_p[chipnr]->msgobj[objnr]->obj_base_addr=(objnr+1)*0x10;
111         chips_p[chipnr]->msgobj[objnr]->flags=0;
112
113         return 0;
114 }
115
116
117 void smartcan_write_register(unsigned char data, unsigned long address)
118 {
119         disable_irq(smartcan_irq);
120         outb(address-smartcan_base,smartcan_base);
121         outb(data,smartcan_base+1);
122         enable_irq(smartcan_irq);
123 }
124
125 unsigned smartcan_read_register(unsigned long address)
126 {
127         unsigned ret;
128         disable_irq(smartcan_irq);
129         outb(address-smartcan_base,smartcan_base);
130         ret=inb(smartcan_base+1);
131         enable_irq(smartcan_irq);
132         return ret;
133 }
134
135 int smartcan_program_irq(int card)
136 {
137         CANMSG("The 'smartcan' card doesn't have programmable interrupts\n");
138         return 0;
139 }
140
141 /* !!! Don't change this function !!! */
142 int smartcan_register(struct hwspecops_t *hwspecops)
143 {
144         hwspecops->request_io = smartcan_request_io;
145         hwspecops->release_io = smartcan_release_io;
146         hwspecops->reset = smartcan_reset;
147         hwspecops->init_hw_data = smartcan_init_hw_data;
148         hwspecops->init_chip_data = smartcan_init_chip_data;
149         hwspecops->init_obj_data = smartcan_init_obj_data;
150         hwspecops->write_register = smartcan_write_register;
151         hwspecops->read_register = smartcan_read_register;
152         hwspecops->program_irq = smartcan_program_irq;
153         return 0;
154 }