]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/pip.c
CAN driver infrastructure redesign to LinCAN-0.2 version
[lincan.git] / lincan / src / pip.c
1 /* pip.c
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.2  9 Jul 2003
8  */ 
9
10 #include <linux/autoconf.h>
11
12 #include <linux/ioport.h>
13 #include <linux/delay.h>
14 #include <linux/string.h>
15 #include <asm/errno.h>
16 #include <asm/io.h>
17
18 #include "../include/main.h"
19 #include "../include/pip.h"
20 #include "../include/i82527.h"
21
22 int pip5_request_io(struct candevice_t *candev)
23 {
24         if (candev->io_addr != 0x8000) {
25                 CANMSG("Invalid base io address\n");
26                 CANMSG("The PIP5 uses a fixed base address of 0x8000,\n");
27                 CANMSG("please consult your user manual.\n");
28                 return -ENODEV;
29         }
30         if (!can_request_io_region(candev->io_addr,0x100,DEVICE_NAME)) {
31                 CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
32                 return -ENODEV;
33         }
34         else if(!can_request_io_region(candev->io_addr+0x102,0x01,DEVICE_NAME)) {
35                 can_release_io_region(candev->io_addr,0x100);
36                 CANMSG("Unable to open port: 0x%lx\n",candev->io_addr+0x102);
37                 return -ENODEV;
38         }
39         else {
40                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + 0x100 - 1);
41                 DEBUGMSG("Registered IO-memory: 0x%lx\n", candev->io_addr+0x102);
42         }
43         return 0;
44 }
45
46 int pip6_request_io(struct candevice_t *candev)
47 {
48         if ( (candev->io_addr != 0x1000)&&(candev->io_addr != 0x8000)&&(candev->io_addr != 0xe000)) {
49                 CANMSG("Invalid base io address\n");
50                 CANMSG("Valid values for the PIP6 are: 0x1000, 0x8000 or 0xe000\n");
51                 CANMSG("Please consult your user manual.\n");
52                 return -ENODEV;
53         }
54         if (!can_request_io_region(candev->io_addr,0x100, DEVICE_NAME)) {
55                 CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
56                 return -ENODEV;
57         }
58         else if (!can_request_io_region(0x804,0x02,DEVICE_NAME)) {
59                 can_release_io_region(candev->io_addr,0x100);
60                 CANMSG("Unable to open port: 0x%x\n", 0x804);
61                 return -ENODEV;
62         }
63         else {
64                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + 0x100 -1);
65                 DEBUGMSG("Registered IO-memory : 0x%x - 0x%x\n",0x804,0x805);
66         }
67         return 0;
68 }
69
70 int pip5_release_io(struct candevice_t *candev)
71 {
72         can_release_io_region(candev->io_addr,0x100);
73         can_release_io_region(candev->io_addr+0x102,0x01);
74
75         return 0;
76 }
77
78 int pip6_release_io(struct candevice_t *candev)
79 {
80         can_release_io_region(candev->io_addr,0x100);
81         can_release_io_region(0x804,0x02);
82
83         return 0;
84 }
85
86 int pip_reset(struct candevice_t *candev)
87 {
88         int i=0, res_value=0;
89
90         DEBUGMSG("Resetting %s hardware ...\n", candev->hwname);
91         if (!strcmp(candev->hwname,"pip5"))
92                 res_value = 0xcf;
93         else
94                 res_value = 0x01;
95         while (i < 1000000) {
96                 i++;
97                 outb(res_value,candev->res_addr);
98         }
99         outb(0x0,candev->res_addr);
100
101         /* Check hardware reset status */
102         i=0;
103         while ( (inb(candev->io_addr+iCPU) & iCPU_RST) && (i<=15)) {
104                 udelay(20000);
105                 i++;
106         }
107         if (i>=15) {
108                 CANMSG("Reset status timeout!\n");
109                 CANMSG("Please check your hardware.\n");
110                 return -ENODEV;
111         }
112         else
113                 DEBUGMSG("Chip0 reset status ok.\n");
114         
115
116         return 0;
117 }
118
119 int pip_init_hw_data(struct candevice_t *candev) 
120 {
121         if (!strcmp(candev->hwname,"pip5"))
122                 candev->res_addr=candev->io_addr+0x102;
123         else
124                 candev->res_addr=0x805;
125         candev->nr_82527_chips=1;
126         candev->nr_sja1000_chips=0;
127         candev->nr_all_chips=1;
128         candev->flags |= PROGRAMMABLE_IRQ;
129
130         return 0;
131 }
132
133 int pip_init_chip_data(struct candevice_t *candev, int chipnr)
134 {
135         candev->chip[chipnr]->chip_type="i82527";
136         candev->chip[chipnr]->chip_base_addr=candev->io_addr;
137         candev->chip[chipnr]->clock = 16000000;
138         if (!strcmp(candev->hwname,"pip5"))
139                 candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
140         else
141                 candev->chip[chipnr]->int_cpu_reg = 0x0;
142         candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
143         candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
144         candev->chip[chipnr]->sja_cdr_reg = 0;
145         candev->chip[chipnr]->sja_ocr_reg = 0;
146
147         return 0;
148 }
149
150 int pip_init_obj_data(struct chip_t *chip, int objnr)
151 {
152         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
153         chip->msgobj[objnr]->flags=0;
154         
155         return 0;
156 }
157
158 int pip5_program_irq(struct candevice_t *candev)
159 {
160         outb(0x01, candev->res_addr);
161         switch (candev->chip[0]->chip_irq) {
162                 case  3: { outb(0x03, candev->res_addr); break; }
163                 case  4: { outb(0x05, candev->res_addr); break; }
164                 case  5: { outb(0x07, candev->res_addr); break; }
165                 case 10: { outb(0x09, candev->res_addr); break; }
166                 case 11: { outb(0x0c, candev->res_addr); break; }
167                 case 15: { outb(0x0d, candev->res_addr); break; }
168                 default: {
169                 CANMSG("Supplied interrupt is not supported by the hardware\n");
170                 CANMSG("Please consult your user manual.\n");
171                 return -ENODEV;
172                 }
173         }
174         outb(0x00, candev->res_addr);
175
176         return 0;
177 }
178
179 int pip6_program_irq(struct candevice_t *candev)
180 {
181         unsigned char can_int = 0, can_addr = 0;
182
183         can_int = candev->chip[0]->chip_irq;
184         if ((can_int != 3) && (can_int != 4) && (can_int != 5) && (can_int != 6)
185                 && (can_int != 7) && (can_int != 9) && (can_int != 10) && 
186                 (can_int != 11) && (can_int != 12) && (can_int != 14) && 
187                 (can_int != 15)) {
188                 CANMSG("Invalid interrupt number\n");
189                 CANMSG("Valid interrupt numbers for the PIP6: 3,4,5,6,7,9,10,11,12,14 or 15\n");
190                 CANMSG("Please consult your user manual.\n");
191                 return -ENODEV;
192         }
193         switch (candev->io_addr) {
194                 case 0x1000: { can_addr = 0x01; break; }
195                 case 0x8000: { can_addr = 0x02; break; }
196                 case 0xe000: { can_addr = 0x03; break; }
197                 default: {
198                 CANMSG("Supplied io address is not valid, please check your manual\n");
199                 return -ENODEV;
200                 }
201         }
202         outb( (can_int<<4)|can_addr, 0x804);
203
204         return 0;
205 }
206
207 void pip_write_register(unsigned char data, unsigned long address)
208 {
209         outb(data,address);
210 }
211
212 unsigned pip_read_register(unsigned long address)
213 {
214         return inb(address);
215 }
216
217 /* !!! Don't change these functions !!! */
218 int pip5_register(struct hwspecops_t *hwspecops)
219 {
220         hwspecops->request_io = pip5_request_io;
221         hwspecops->release_io = pip5_release_io;
222         hwspecops->reset = pip_reset;
223         hwspecops->init_hw_data = pip_init_hw_data;
224         hwspecops->init_chip_data = pip_init_chip_data;
225         hwspecops->init_obj_data = pip_init_obj_data;
226         hwspecops->write_register = pip_write_register;
227         hwspecops->read_register = pip_read_register;
228         hwspecops->program_irq = pip5_program_irq;
229         return 0;
230 }
231
232 int pip6_register(struct hwspecops_t *hwspecops)
233 {
234         hwspecops->request_io = pip6_request_io;
235         hwspecops->release_io = pip6_release_io;
236         hwspecops->reset = pip_reset;
237         hwspecops->init_hw_data = pip_init_hw_data;
238         hwspecops->init_chip_data = pip_init_chip_data;
239         hwspecops->init_obj_data = pip_init_obj_data;
240         hwspecops->write_register = pip_write_register;
241         hwspecops->read_register = pip_read_register;
242         hwspecops->program_irq = pip6_program_irq;
243         return 0;
244 }