]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/i82527.c
5ab2dcfb449e28db3b74b7b8de099ae205fc5279
[lincan.git] / lincan / src / i82527.c
1 /* i82527.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 #define __NO_VERSION__
9 #include <linux/module.h>
10
11 #include <linux/autoconf.h>
12 #if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
13 #define MODVERSIONS
14 #endif
15
16 #if defined (MODVERSIONS)
17 #include <linux/modversions.h>
18 #endif
19
20 #include <linux/fs.h>
21
22 #include "../include/main.h"
23 #include "../include/i82527.h"
24
25 extern int stdmask;
26 extern int extmask;
27 extern int mo15mask;
28
29 int i82527_enable_configuration(struct chip_t *chip)
30 {
31         unsigned short flags=0;
32
33         flags = can_read_reg(chip, iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
34         can_write_reg(chip, flags|iCTL_CCE, iCTL);
35         
36         return 0;
37 }
38
39 int i82527_disable_configuration(struct chip_t *chip)
40 {
41         unsigned short flags=0;
42
43         flags = can_read_reg(chip, iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
44         can_write_reg(chip, flags, iCTL);
45
46         return 0;
47 }
48
49 int i82527_chip_config(struct chip_t *chip)
50 {
51         can_write_reg(chip,chip->int_cpu_reg,iCPU); // Configure cpu interface
52         can_write_reg(chip,(iCTL_CCE|iCTL_INI),iCTL); // Enable configuration
53         can_write_reg(chip,chip->int_clk_reg,iCLK); // Set clock out slew rates 
54         can_write_reg(chip,chip->int_bus_reg,iBUS); /* Bus configuration */
55         can_write_reg(chip,0x00,iSTAT); /* Clear error status register */
56
57         /* Check if we can at least read back some arbitrary data from the 
58          * card. If we can not, the card is not properly configured!
59          */
60         can_write_reg(chip,0x25,MSG_OFFSET(1)+iMSGDAT1);
61         can_write_reg(chip,0x52,MSG_OFFSET(2)+iMSGDAT3);
62         can_write_reg(chip,0xc3,MSG_OFFSET(10)+iMSGDAT6);
63         if ( (can_read_reg(chip,MSG_OFFSET(1)+iMSGDAT1) != 0x25) ||
64               (can_read_reg(chip,MSG_OFFSET(2)+iMSGDAT3) != 0x52) ||
65               (can_read_reg(chip,MSG_OFFSET(10)+iMSGDAT6) != 0xc3) ) {
66                 CANMSG("Could not read back from the hardware.\n");
67                 CANMSG("This probably means that your hardware is not correctly configured!\n");
68                 return -1;
69         }
70         else
71                 DEBUGMSG("Could read back, hardware is probably configured correctly\n");
72
73         if (baudrate == 0)
74                 baudrate=1000;
75
76         if (i82527_baud_rate(chip,baudrate*1000,chip->clock,0,75,0)) {
77                 CANMSG("Error configuring baud rate\n");
78                 return -ENODEV;
79         }
80         if (i82527_standard_mask(chip,0x0000,stdmask)) {
81                 CANMSG("Error configuring standard mask\n");
82                 return -ENODEV;
83         }
84         if (i82527_extended_mask(chip,0x00000000,extmask)) {
85                 CANMSG("Error configuring extended mask\n");
86                 return -ENODEV;
87         }
88         if (i82527_message15_mask(chip,0x00000000,mo15mask)) {
89                 CANMSG("Error configuring message 15 mask\n");
90                 return -ENODEV;
91         }
92         if (i82527_clear_objects(chip)) {
93                 CANMSG("Error clearing message objects\n");
94                 return -ENODEV;
95         }
96         if (i82527_config_irqs(chip,0x0a)) {
97                 CANMSG("Error configuring interrupts\n");
98                 return -ENODEV;
99         }
100
101         return 0;
102 }
103
104 /* Set communication parameters.
105  * param rate baud rate in Hz
106  * param clock frequency of i82527 clock in Hz (ISA osc is 14318000)
107  * param sjw synchronization jump width (0-3) prescaled clock cycles
108  * param sampl_pt sample point in % (0-100) sets (TSEG1+2)/(TSEG1+TSEG2+3) ratio
109  * param flags fields BTR1_SAM, OCMODE, OCPOL, OCTP, OCTN, CLK_OFF, CBP
110  */
111 int i82527_baud_rate(struct chip_t *chip, int rate, int clock, int sjw,
112                                                         int sampl_pt, int flags)
113 {
114         int best_error = 1000000000, error;
115         int best_tseg=0, best_brp=0, best_rate=0, brp=0;
116         int tseg=0, tseg1=0, tseg2=0;
117         
118         if (i82527_enable_configuration(chip))
119                 return -ENODEV;
120
121         clock /=2;
122
123         /* tseg even = round down, odd = round up */
124         for (tseg=(0+0+2)*2; tseg<=(MAX_TSEG2+MAX_TSEG1+2)*2+1; tseg++) {
125                 brp = clock/((1+tseg/2)*rate)+tseg%2;
126                 if (brp == 0 || brp > 64)
127                         continue;
128                 error = rate - clock/(brp*(1+tseg/2));
129                 if (error < 0)
130                         error = -error;
131                 if (error <= best_error) {
132                         best_error = error;
133                         best_tseg = tseg/2;
134                         best_brp = brp-1;
135                         best_rate = clock/(brp*(1+tseg/2));
136                 }
137         }
138         if (best_error && (rate/best_error < 10)) {
139                 CANMSG("baud rate %d is not possible with %d Hz clock\n",
140                                                                 rate, 2*clock);
141                 CANMSG("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d\n",
142                                 best_rate, best_brp, best_tseg, tseg1, tseg2);
143                 return -EINVAL;
144         }
145         tseg2 = best_tseg-(sampl_pt*(best_tseg+1))/100;
146         if (tseg2 < 0)
147                 tseg2 = 0;
148         if (tseg2 > MAX_TSEG2)
149                 tseg2 = MAX_TSEG2;
150         
151         tseg1 = best_tseg-tseg2-2;
152         if (tseg1>MAX_TSEG1) {
153                 tseg1 = MAX_TSEG1;
154                 tseg2 = best_tseg-tseg1-2;
155         }
156
157         DEBUGMSG("Setting %d bps.\n", best_rate);
158         DEBUGMSG("brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d, sampl_pt=%d\n",
159                                         best_brp, best_tseg, tseg1, tseg2,
160                                         (100*(best_tseg-tseg2)/(best_tseg+1)));
161                                         
162                                 
163         can_write_reg(chip, sjw<<6 | best_brp, iBT0);
164         can_write_reg(chip, ((flags & BTR1_SAM) != 0)<<7 | tseg2<<4 | tseg1,
165                                                                 iBT1);
166         DEBUGMSG("Writing 0x%x to iBT0\n",(sjw<<6 | best_brp));
167         DEBUGMSG("Writing 0x%x to iBT1\n",((flags & BTR1_SAM) != 0)<<7 | 
168                                                         tseg2<<4 | tseg1);
169
170         i82527_disable_configuration(chip);
171
172         return 0;
173 }
174
175 int i82527_standard_mask(struct chip_t *chip, unsigned short code, unsigned short mask)
176 {
177         unsigned char mask0, mask1;
178
179         mask0 = (unsigned char) (mask >> 3);
180         mask1 = (unsigned char) (mask << 5);
181         
182         can_write_reg(chip,mask0,iSGM0);
183         can_write_reg(chip,mask1,iSGM1);
184
185         DEBUGMSG("Setting standard mask to 0x%lx\n",(unsigned long)mask);
186
187         return 0;
188 }
189
190 int i82527_extended_mask(struct chip_t *chip, unsigned long code, unsigned long mask)
191 {
192         unsigned char mask0, mask1, mask2, mask3;
193
194         mask0 = (unsigned char) (mask >> 21);
195         mask1 = (unsigned char) (mask >> 13);
196         mask2 = (unsigned char) (mask >> 5);
197         mask3 = (unsigned char) (mask << 3);
198
199         can_write_reg(chip,mask0,iEGM0);
200         can_write_reg(chip,mask1,iEGM1);
201         can_write_reg(chip,mask2,iEGM2);
202         can_write_reg(chip,mask3,iEGM3);
203
204         DEBUGMSG("Setting extended mask to 0x%lx\n",(unsigned long)mask);
205
206         return 0;
207 }
208
209 int i82527_message15_mask(struct chip_t *chip, unsigned long code, unsigned long mask)
210 {
211         unsigned char mask0, mask1, mask2, mask3;
212
213         mask0 = (unsigned char) (mask >> 21);
214         mask1 = (unsigned char) (mask >> 13);
215         mask2 = (unsigned char) (mask >> 5);
216         mask3 = (unsigned char) (mask << 3);
217
218         can_write_reg(chip,mask0,i15M0);
219         can_write_reg(chip,mask1,i15M1);
220         can_write_reg(chip,mask2,i15M2);
221         can_write_reg(chip,mask3,i15M3);
222
223         DEBUGMSG("Setting message 15 mask to 0x%lx\n",mask);
224
225         return 0;
226
227
228 }
229
230 int i82527_clear_objects(struct chip_t *chip)
231 {
232         int i=0,id=0,data=0;
233
234         DEBUGMSG("Cleared all message objects on chip\n");
235
236         for (i=1; i<=15; i++) {
237                 can_write_reg(chip,(INTPD_RES|RXIE_RES|TXIE_RES|MVAL_RES) ,
238                                                         MSG_OFFSET(i)+iMSGCTL0);
239                 can_write_reg(chip,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES) ,
240                                                         MSG_OFFSET(i)+iMSGCTL1);
241                 for (data=0x07; data<0x0f; data++)
242                         can_write_reg(chip,0x00,MSG_OFFSET(i)+data);
243                 for (id=2; id<6; id++) {
244                         can_write_reg(chip,0x00,MSG_OFFSET(i)+id);
245                 }
246                 if (extended==0) {
247                         can_write_reg(chip,0x00,MSG_OFFSET(i)+iMSGCFG);
248                 }
249                 else {
250                         can_write_reg(chip,MCFG_XTD,MSG_OFFSET(i)+iMSGCFG);
251                 }
252         }
253         if (extended==0)
254                 DEBUGMSG("All message ID's set to standard\n");
255         else
256                 DEBUGMSG("All message ID's set to extended\n");
257         
258         return 0;
259 }
260
261 int i82527_config_irqs(struct chip_t *chip, short irqs)
262 {
263         can_write_reg(chip,irqs,iCTL);
264         DEBUGMSG("Configured hardware interrupt delivery\n");
265         return 0;
266 }
267
268 int i82527_pre_read_config(struct chip_t *chip, struct msgobj_t *obj)
269 {
270         if (extended) {
271                 can_write_reg(chip,MCFG_XTD,MSG_OFFSET(obj->object)+iMSGCFG);
272         }
273         else {
274                 can_write_reg(chip,0x00,MSG_OFFSET(obj->object)+iMSGCFG);
275         }
276         can_write_reg(chip ,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES),
277                                         MSG_OFFSET(obj->object)+iMSGCTL1);
278         can_write_reg(chip ,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),
279                                         MSG_OFFSET(obj->object)+iMSGCTL0);
280         
281         return 0;
282 }
283
284 int i82527_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, 
285                                                         struct canmsg_t *msg)
286 {
287         int i=0,id0=0,id1=0,id2=0,id3=0;
288
289         can_write_reg(chip,(RMPD_RES|TXRQ_RES|CPUU_SET|NEWD_RES),
290                                         MSG_OFFSET(obj->object)+iMSGCTL1);
291         can_write_reg(chip,(MVAL_SET|TXIE_SET|RXIE_RES|INTPD_RES),
292                                         MSG_OFFSET(obj->object)+iMSGCTL0);
293         if (extended) {
294                 can_write_reg(chip,(msg->length<<4)+(MCFG_DIR|MCFG_XTD),
295                                         MSG_OFFSET(obj->object)+iMSGCFG);
296         }
297         else {
298                 can_write_reg(chip,(msg->length<<4)+MCFG_DIR,
299                                         MSG_OFFSET(obj->object)+iMSGCFG);
300         }
301         if (extended) {
302                 id0 = (unsigned char) (msg->id<<3);
303                 id1 = (unsigned char) (msg->id>>5);
304                 id2 = (unsigned char) (msg->id>>13);
305                 id3 = (unsigned char) (msg->id>>21);
306                 can_write_reg(chip,id0,MSG_OFFSET(obj->object)+iMSGID3);
307                 can_write_reg(chip,id1,MSG_OFFSET(obj->object)+iMSGID2);
308                 can_write_reg(chip,id2,MSG_OFFSET(obj->object)+iMSGID1);
309                 can_write_reg(chip,id3,MSG_OFFSET(obj->object)+iMSGID0);
310         }
311         else {
312                 id1 = (unsigned char) (msg->id<<5);
313                 id0 = (unsigned char) (msg->id>>3);
314                 can_write_reg(chip,id1,MSG_OFFSET(obj->object)+iMSGID1);
315                 can_write_reg(chip,id0,MSG_OFFSET(obj->object)+iMSGID0);
316         }
317         can_write_reg(chip,0xfa,MSG_OFFSET(obj->object)+iMSGCTL1);
318         for (i=0; i<msg->length; i++) {
319                 can_write_reg(chip,msg->data[i],MSG_OFFSET(obj->object)+
320                                                                 iMSGDAT0+i);
321         }
322
323         return 0;
324 }
325
326 int i82527_send_msg(struct chip_t *chip, struct msgobj_t *obj,
327                                                         struct canmsg_t *msg)
328 {
329         if (msg->flags & MSG_RTR) {
330                 can_write_reg(chip,(RMPD_RES|TXRQ_RES|CPUU_RES|NEWD_SET),
331                                         MSG_OFFSET(obj->object)+iMSGCTL1);
332         }
333         else {
334                 can_write_reg(chip,(RMPD_RES|TXRQ_SET|CPUU_RES|NEWD_SET),
335                                         MSG_OFFSET(obj->object)+iMSGCTL1);
336         }
337
338         return 0;
339 }
340
341 int i82527_check_tx_stat(struct chip_t *chip)
342 {
343         if (can_read_reg(chip,iSTAT) & iSTAT_TXOK) {
344                 can_write_reg(chip,0x0,iSTAT);
345                 return 0;
346         }
347         else {
348                 can_write_reg(chip,0x0,iSTAT);
349                 return 1;
350         }
351 }
352
353 int i82527_remote_request(struct chip_t *chip, struct msgobj_t *obj)
354 {
355         can_write_reg(chip, (MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES), 
356                                         MSG_OFFSET(obj->object)+iMSGCTL0);
357         can_write_reg(chip, (RMPD_RES|TXRQ_SET|MLST_RES|NEWD_RES), 
358                                         MSG_OFFSET(obj->object)+iMSGCTL1);
359         
360         return 0;
361 }
362
363 int i82527_set_btregs(struct chip_t *chip, unsigned short btr0,
364                                                         unsigned short btr1)
365 {
366         if (i82527_enable_configuration(chip))
367                 return -ENODEV;
368
369         can_write_reg(chip, btr0, iBT0);
370         can_write_reg(chip, btr1, iBT1);
371
372         i82527_disable_configuration(chip);
373
374         return 0;
375 }
376
377 int i82527_start_chip(struct chip_t *chip)
378 {
379         unsigned short flags = 0;
380
381         flags = can_read_reg(chip, iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
382         can_write_reg(chip, flags, iCTL);
383         
384         return 0;
385 }
386
387 int i82527_stop_chip(struct chip_t *chip)
388 {
389         unsigned short flags = 0;
390
391         flags = can_read_reg(chip, iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
392         can_write_reg(chip, flags|(iCTL_CCE|iCTL_INI), iCTL);
393
394         return 0;
395 }
396
397 int i82527_register(struct chipspecops_t *chipspecops)
398 {
399         chipspecops->chip_config = i82527_chip_config;
400         chipspecops->baud_rate = i82527_baud_rate;
401         chipspecops->standard_mask = i82527_standard_mask;
402         chipspecops->extended_mask = i82527_extended_mask;
403         chipspecops->message15_mask = i82527_message15_mask;
404         chipspecops->clear_objects = i82527_clear_objects;
405         chipspecops->config_irqs = i82527_config_irqs;
406         chipspecops->pre_read_config = i82527_pre_read_config;
407         chipspecops->pre_write_config = i82527_pre_write_config;
408         chipspecops->send_msg = i82527_send_msg;
409         chipspecops->check_tx_stat = i82527_check_tx_stat;
410         chipspecops->remote_request = i82527_remote_request;
411         chipspecops->enable_configuration = i82527_enable_configuration;
412         chipspecops->disable_configuration = i82527_disable_configuration;
413         chipspecops->set_btregs = i82527_set_btregs;
414         chipspecops->start_chip = i82527_start_chip;
415         chipspecops->stop_chip = i82527_stop_chip;
416         return 0;
417 }