]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/bfadcan.c
LinCAN driver major structured comments and documentation update
[lincan.git] / lincan / src / bfadcan.c
1 /* bfadcan.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 /* This file is intended as a bfadcan file for currently unsupported hardware.
11  * Once you've changed/added the functions specific to your hardware it is
12  * possible to load the driver with the hardware option hw=bfadcan.
13  */
14
15 #define __NO_VERSION__ /* this is not a main module, do not include module info */
16
17 #include <linux/autoconf.h>
18
19 #include <linux/module.h>
20
21 #include <linux/version.h>
22 #include <linux/ioport.h>
23 #include <linux/delay.h>
24 #include <asm/errno.h>
25 #include <asm/io.h>
26
27 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
28 #include <asm/spinlock.h>
29 #else
30 #include <linux/spinlock.h>
31 #endif
32
33 #define WINDOWED_ACCESS
34
35 #include "../include/main.h"
36 #include "../include/i82527.h"
37 #include "../include/sja1000p.h"
38
39 long clock_freq;
40 MODULE_PARM(clock_freq,"i");
41
42 /* cli and sti are not allowed in 2.5.5x SMP kernels */
43 #ifdef WINDOWED_ACCESS
44 spinlock_t bfadcan_win_lock=SPIN_LOCK_UNLOCKED;
45 #endif
46
47 /*
48  * IO_RANGE is the io-memory range that gets reserved, please adjust according
49  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
50  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
51  */
52 #ifdef WINDOWED_ACCESS
53 #define IO_RANGE 0x4
54 #else
55 #define IO_RANGE 0x100
56 #endif
57
58 unsigned bfadcan_read_register(unsigned long address);
59 void bfadcan_write_register(unsigned char data, unsigned long address);
60
61
62 /**
63  * bfadcan_request_io: - reserve io or memory range for can board
64  * @candev: pointer to candevice/board which asks for io. Field @io_addr
65  *      of @candev is used in most cases to define start of the range
66  *
67  * The function bfadcan_request_io() is used to reserve the io-memory. If your
68  * hardware uses a dedicated memory range as hardware control registers you
69  * will have to add the code to reserve this memory as well. 
70  * %IO_RANGE is the io-memory range that gets reserved, please adjust according
71  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
72  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
73  * Return Value: The function returns zero on success or %-ENODEV on failure
74  * File: src/bfadcan.c
75  */
76 int bfadcan_request_io(struct candevice_t *candev)
77 {
78         if (!can_request_io_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
79                 CANMSG("Unable to open port: 0x%lx\n",candev->io_addr);
80                 return -ENODEV;
81         } else {
82                 DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
83         }
84         return 0;
85 }
86
87 /**
88  * bfadcan_elease_io - free reserved io memory range
89  * @candev: pointer to candevice/board which releases io
90  *
91  * The function bfadcan_release_io() is used to free reserved io-memory.
92  * In case you have reserved more io memory, don't forget to free it here.
93  * IO_RANGE is the io-memory range that gets released, please adjust according
94  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
95  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
96  * Return Value: The function always returns zero
97  * File: src/bfadcan.c
98  */
99 int bfadcan_release_io(struct candevice_t *candev)
100 {
101         can_release_io_region(candev->io_addr,IO_RANGE);
102
103         return 0;
104 }
105
106 /**
107  * bfadcan_reset - hardware reset routine
108  * @candev: Pointer to candevice/board structure
109  *
110  * The function bfadcan_reset() is used to give a hardware reset. This is 
111  * rather hardware specific so I haven't included example code. Don't forget to 
112  * check the reset status of the chip before returning.
113  * Return Value: The function returns zero on success or %-ENODEV on failure
114  * File: src/bfadcan.c
115  */
116 int bfadcan_reset(struct candevice_t *candev)
117 {
118
119         int i;
120         struct chip_t *chip=candev->chip[0];
121         unsigned cdr;
122         
123         bfadcan_write_register(MOD_RM, chip->chip_base_addr+SJAMOD);
124         udelay(1000);
125         
126         cdr=bfadcan_read_register(chip->chip_base_addr+SJACDR);
127         bfadcan_write_register(cdr|CDR_PELICAN, chip->chip_base_addr+SJACDR);
128
129         bfadcan_write_register(0, chip->chip_base_addr+SJAIER);
130
131         i=20;
132         bfadcan_write_register(0, chip->chip_base_addr+SJAMOD);
133         while (bfadcan_read_register(chip->chip_base_addr+SJAMOD)&MOD_RM){
134                 if(!i--) return -ENODEV;
135                 udelay(1000);
136                 bfadcan_write_register(0, chip->chip_base_addr+SJAMOD);
137         }
138
139         cdr=bfadcan_read_register(chip->chip_base_addr+SJACDR);
140         bfadcan_write_register(cdr|CDR_PELICAN, chip->chip_base_addr+SJACDR);
141
142         bfadcan_write_register(0, chip->chip_base_addr+SJAIER);
143         
144         return 0;
145 }
146
147 #define RESET_ADDR 0x202
148 #define NR_82527 0
149 #define NR_SJA1000 1
150
151 /**
152  * bfadcan_init_hw_data - Initialize hardware cards
153  * @candev: Pointer to candevice/board structure
154  *
155  * The function bfadcan_init_hw_data() is used to initialize the hardware
156  * structure containing information about the installed CAN-board.
157  * %RESET_ADDR represents the io-address of the hardware reset register.
158  * %NR_82527 represents the number of intel 82527 chips on the board.
159  * %NR_SJA1000 represents the number of philips sja1000 chips on the board.
160  * The flags entry can currently only be %PROGRAMMABLE_IRQ to indicate that
161  * the hardware uses programmable interrupts.
162  * Return Value: The function always returns zero
163  * File: src/bfadcan.c
164  */
165 int bfadcan_init_hw_data(struct candevice_t *candev) 
166 {
167         candev->res_addr=RESET_ADDR;
168         candev->nr_82527_chips=NR_82527;
169         candev->nr_sja1000_chips=NR_SJA1000;
170         candev->nr_all_chips=NR_82527+NR_SJA1000;
171         candev->flags |= 0 /* PROGRAMMABLE_IRQ */ ;
172
173         return 0;
174 }
175
176 #define CHIP_TYPE "sja1000p"
177 /**
178  * bfadcan_init_chip_data - Initialize chips
179  * @candev: Pointer to candevice/board structure
180  * @chipnr: Number of the CAN chip on the hardware card
181  *
182  * The function bfadcan_init_chip_data() is used to initialize the hardware
183  * structure containing information about the CAN chips.
184  * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
185  * "sja1000".
186  * The @chip_base_addr entry represents the start of the 'official' memory map
187  * of the installed chip. It's likely that this is the same as the @io_addr
188  * argument supplied at module loading time.
189  * The @clock entry holds the chip clock value in Hz.
190  * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
191  * register. Options defined in the %sja1000.h file:
192  * %CDR_CLKOUT_MASK, %CDR_CLK_OFF, %CDR_RXINPEN, %CDR_CBP, %CDR_PELICAN
193  * The entry @sja_ocr_reg holds hardware specific options for the Output Control
194  * register. Options defined in the %sja1000.h file:
195  * %OCR_MODE_BIPHASE, %OCR_MODE_TEST, %OCR_MODE_NORMAL, %OCR_MODE_CLOCK,
196  * %OCR_TX0_LH, %OCR_TX1_ZZ.
197  * The entry @int_clk_reg holds hardware specific options for the Clock Out
198  * register. Options defined in the %i82527.h file:
199  * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
200  * The entry @int_bus_reg holds hardware specific options for the Bus 
201  * Configuration register. Options defined in the %i82527.h file:
202  * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
203  * The entry @int_cpu_reg holds hardware specific options for the cpu interface
204  * register. Options defined in the %i82527.h file:
205  * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
206  * Return Value: The function always returns zero
207  * File: src/bfadcan.c
208  */
209 int bfadcan_init_chip_data(struct candevice_t *candev, int chipnr)
210 {
211         unsigned int id1, id2;
212         candev->chip[chipnr]->chip_type=CHIP_TYPE;
213         candev->chip[chipnr]->chip_base_addr=candev->io_addr;
214         candev->chip[chipnr]->clock = clock_freq;
215         candev->chip[chipnr]->int_cpu_reg = iCPU_DSC;
216         candev->chip[chipnr]->int_clk_reg = iCLK_SL1;
217         candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
218         candev->chip[chipnr]->sja_cdr_reg = CDR_CBP | CDR_CLK_OFF;
219         candev->chip[chipnr]->sja_ocr_reg = OCR_MODE_NORMAL |
220                                                                 OCR_TX0_LH;
221         id1 = inb(0xe284);
222         id2 = inb(0xe285);
223
224
225         CANMSG("can driver ver lincan-0.2, at %04lx, CPLD v%d.%d.%d.%d\n",
226                                         candev->chip[chipnr]->chip_base_addr,
227                                                         id1>>4, id1&0x0f, id2>>4, id2&0x0f);
228
229
230         return 0;
231 }
232
233 /**
234  * bfadcan_init_obj_data - Initialize message buffers
235  * @chip: Pointer to chip specific structure
236  * @objnr: Number of the message buffer
237  *
238  * The function bfadcan_init_obj_data() is used to initialize the hardware
239  * structure containing information about the different message objects on the
240  * CAN chip. In case of the sja1000 there's only one message object but on the
241  * i82527 chip there are 15.
242  * The code below is for a i82527 chip and initializes the object base addresses
243  * The entry @obj_base_addr represents the first memory address of the message 
244  * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
245  * base address.
246  * Unless the hardware uses a segmented memory map, flags can be set zero.
247  * Return Value: The function always returns zero
248  * File: src/bfadcan.c
249  */
250 int bfadcan_init_obj_data(struct chip_t *chip, int objnr)
251 {
252         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
253         chip->msgobj[objnr]->flags=0;
254         
255         return 0;
256 }
257
258 /**
259  * bfadcan_program_irq - program interrupts
260  * @candev: Pointer to candevice/board structure
261  *
262  * The function bfadcan_program_irq() is used for hardware that uses 
263  * programmable interrupts. If your hardware doesn't use programmable interrupts
264  * you should not set the @candevices_t->flags entry to %PROGRAMMABLE_IRQ and 
265  * leave this function unedited. Again this function is hardware specific so 
266  * there's no example code.
267  * Return value: The function returns zero on success or %-ENODEV on failure
268  * File: src/bfadcan.c
269  */
270 int bfadcan_program_irq(struct candevice_t *candev)
271 {
272         return 0;
273 }
274
275 /**
276  * bfadcan_write_register - Low level write register routine
277  * @data: data to be written
278  * @address: memory address to write to
279  *
280  * The function bfadcan_write_register() is used to write to hardware registers
281  * on the CAN chip. You should only have to edit this function if your hardware
282  * uses some specific write process.
283  * Return Value: The function does not return a value
284  * File: src/bfadcan.c
285  */
286 void bfadcan_write_register(unsigned char data, unsigned long address)
287 {
288 #ifdef WINDOWED_ACCESS
289         long flags;
290         spin_lock_irqsave(&bfadcan_win_lock,flags);
291         outb(address&0x00ff,0x200);
292         outb(data, 0x201);
293         spin_unlock_irqrestore(&bfadcan_win_lock,flags);
294 #else
295         outb(data,address);
296 #endif
297 }
298
299 /**
300  * bfadcan_read_register - Low level read register routine
301  * @address: memory address to read from
302  *
303  * The function bfadcan_read_register() is used to read from hardware registers
304  * on the CAN chip. You should only have to edit this function if your hardware
305  * uses some specific read process.
306  * Return Value: The function returns the value stored in @address
307  * File: src/bfadcan.c
308  */
309 unsigned bfadcan_read_register(unsigned long address)
310 {
311 #ifdef WINDOWED_ACCESS
312         long flags;
313         int ret;
314         spin_lock_irqsave(&bfadcan_win_lock,flags);
315         outb(address&0x00ff,0x200);
316         ret = inb(0x201);
317         spin_unlock_irqrestore(&bfadcan_win_lock,flags);
318         return ret;
319 #else
320         return inb(address);
321 #endif
322 }
323
324 /* !!! Don't change this function !!! */
325 int bfadcan_register(struct hwspecops_t *hwspecops)
326 {
327         hwspecops->request_io = bfadcan_request_io;
328         hwspecops->release_io = bfadcan_release_io;
329         hwspecops->reset = bfadcan_reset;
330         hwspecops->init_hw_data = bfadcan_init_hw_data;
331         hwspecops->init_chip_data = bfadcan_init_chip_data;
332         hwspecops->init_obj_data = bfadcan_init_obj_data;
333         hwspecops->write_register = bfadcan_write_register;
334         hwspecops->read_register = bfadcan_read_register;
335         hwspecops->program_irq = bfadcan_program_irq;
336         return 0;
337 }