]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/m437.c
00ac7c3ea9b43bec2fed349120675c29c248be38
[lincan.git] / lincan / src / m437.c
1 /* m437.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.3  17 Jun 2004
8  *
9  * 15 July 2008 updated by Philippe Corbes,  email:philippe.corbes@logibag.com
10  * This driver has been designed to support "Memory (MEM)" mode.
11  * For example: Memory, MEM:0xD0000 => io=0xD0000. 
12  * Configure the card with m437set.com provided by seco before loading driver.
13  * This software is released under the GPL-License.
14  */
15
16 /*
17  * Support for the SECO M437
18  *
19  * SECO M437 is a pc104 format, i82527 controller based card
20  * produced by SECO http://www.seco.it
21  * This driver uses the Memory Mapped I/O mode, and should be
22  * working with all cards supporting this mode.
23  *
24  * Written by Fabio Parodi  (fabio.parodi@iname.com)
25  * Additional changes by Giampiero Giancipoli (gianci@freemail.it)
26  *
27  * Version 0.1  08 Jun 2001
28  *
29  */
30
31 #include "../include/can.h"
32 #include "../include/can_sysdep.h"
33 #include "../include/main.h"
34 #include "../include/m437.h"
35 #include "../include/i82527.h"
36
37 /*
38  * IO_RANGE is the io-memory range that gets reserved, please adjust according
39  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
40  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
41  */
42 #define IO_RANGE 0x100
43
44
45 /**
46  * m437_request_io: - reserve io or memory range for can board
47  * @candev: pointer to candevice/board which asks for io. Field @io_addr
48  *      of @candev is used in most cases to define start of the range
49  *
50  * The function m437_request_io() is used to reserve the io-memory. If your
51  * hardware uses a dedicated memory range as hardware control registers you
52  * will have to add the code to reserve this memory as well.
53  * %IO_RANGE is the io-memory range that gets reserved, please adjust according
54  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
55  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
56  * Return Value: The function returns zero on success or %-ENODEV on failure
57  * File: src/m437.c
58  */
59 int m437_request_io(struct candevice_t *candev)
60 {
61         can_ioptr_t remap_addr;
62
63         if (!can_request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME)) {
64                 CANMSG("M437 Unable to request IO-memory: 0x%lx\n",candev->io_addr);
65                 return -ENODEV;
66         }
67
68         if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
69                 CANMSG("M437 Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
70                 can_release_mem_region(candev->io_addr,IO_RANGE);
71                 return -ENODEV;
72
73         }
74         CANMSG("M437 Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
75         CANMSG("M437 IO-memory: 0x%lx  Remapped to: 0x%lx\n", candev->io_addr, remap_addr);
76
77         /* remap the chip and pointers on objects */
78         can_base_addr_fixup(candev, remap_addr);
79
80 #ifdef CAN_DEBUG
81         {
82                 int objnr;
83                 for (objnr=0; objnr<15 ; objnr++) {
84                         DEBUGMSG("M437 Message%d remapped to: 0x%lx\n", objnr+1, candev->chip[0]->msgobj[objnr]->obj_base_addr);
85                 }
86         }
87 #endif /*CAN_DEBUG*/
88
89         return 0;
90 }
91
92 /**
93  * m437_elease_io - free reserved io memory range
94  * @candev: pointer to candevice/board which releases io
95  *
96  * The function m437_release_io() is used to free reserved io-memory.
97  * In case you have reserved more io memory, don't forget to free it here.
98  * IO_RANGE is the io-memory range that gets released, please adjust according
99  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
100  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
101  * Return Value: The function always returns zero
102  * File: src/m437.c
103  */
104 int m437_release_io(struct candevice_t *candev)
105 {
106         /*
107          * The full board reset is more robust solution
108          * than reset of communication objects
109          * Philippe Corbes, 06 jun 2008
110          */
111 #if 0 /* Object reset method */
112         unsigned i;
113         
114         /* disable IRQ generation */
115         m437_write_register(iCTL_CCE, candev->dev_base_addr+iCTL);
116
117         /* clear all message objects */
118         for (i=1; i<=15; i++) {
119                 m437_write_register(
120                                 INTPD_RES | 
121                                 RXIE_RES | 
122                                 TXIE_RES | 
123                                 MVAL_RES, 
124                                 candev->dev_base_addr+i*0x10+iMSGCTL0);
125                 m437_write_register(
126                                 NEWD_RES | 
127                                 MLST_RES | 
128                                 CPUU_RES | 
129                                 TXRQ_RES | 
130                                 RMPD_RES, 
131                                 candev->dev_base_addr+i*0x10+iMSGCTL1);
132         }
133
134         /* power down i82527 */
135         m437_write_register(iCPU_PWD, candev->dev_base_addr+iCPU);
136
137 #else /* Full board reset */
138         m437_reset(candev);
139 #endif /* Full board reset */
140
141         /* release I/O memory mapping */
142         iounmap(candev->dev_base_addr);
143
144         can_release_mem_region(candev->io_addr,IO_RANGE);
145
146         CANMSG("M437 release - OK\n");
147
148         return 0;
149 }
150
151 /**
152  * m437_reset - hardware reset routine
153  * @candev: Pointer to candevice/board structure
154  *
155  * The function m437_reset() is used to give a hardware reset. This is
156  * rather hardware specific so I haven't included example code. Don't forget to
157  * check the reset status of the chip before returning.
158  * Return Value: The function returns zero on success or %-ENODEV on failure
159  * File: src/m437.c
160  * from Philippe Corbes, 08 July 2008
161  */
162 int m437_reset(struct candevice_t *candev)
163 {
164         int i=0;
165
166         DEBUGMSG("Resetting %s hardware ...\n", candev->hwname);
167         for (i = 0 ; i < 10 ; i++) {
168                 m437_write_register(0x01,candev->dev_base_addr+candev->res_addr);
169         }
170         m437_write_register(0x0,candev->dev_base_addr+candev->res_addr);
171
172         /* Check hardware reset status */
173         i=0;
174         while ( (m437_read_register(candev->dev_base_addr+iCPU) & iCPU_RST) && (i<=15)) {
175                 udelay(20000);
176                 i++;
177         }
178         if (i>=15) {
179                 CANMSG("M437 Reset status timeout! Please check your hardware.\n");
180                 return -ENODEV;
181         }
182         else
183                 DEBUGMSG("Chip0 reset status ok.\n");
184
185         return 0;
186 }
187
188 #define RESET_ADDR 0x0
189 #define NR_82527 1
190 #define NR_SJA1000 0
191
192 /**
193  * m437_init_hw_data - Initialize hardware cards
194  * @candev: Pointer to candevice/board structure
195  *
196  * The function m437_init_hw_data() is used to initialize the hardware
197  * structure containing information about the installed CAN-board.
198  * %RESET_ADDR represents the io-address of the hardware reset register.
199  * %NR_82527 represents the number of intel 82527 chips on the board.
200  * %NR_SJA1000 represents the number of philips sja1000 chips on the board.
201  * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
202  * the hardware uses programmable interrupts.
203  * Return Value: The function always returns zero
204  * File: src/m437.c
205  */
206 int m437_init_hw_data(struct candevice_t *candev)
207 {
208         DEBUGMSG("m437_init_hw_data()\n");
209         candev->res_addr=RESET_ADDR;
210         candev->nr_82527_chips=1;
211         candev->nr_sja1000_chips=0;
212         candev->nr_all_chips=1;
213         candev->flags &= ~CANDEV_PROGRAMMABLE_IRQ;
214         /* The M437 has no programmable IRQ */
215
216         return 0;
217 }
218
219 /**
220  * m437_init_chip_data - Initialize chips
221  * @candev: Pointer to candevice/board structure
222  * @chipnr: Number of the CAN chip on the hardware card
223  *
224  * The function m437_init_chip_data() is used to initialize the hardware
225  * structure containing information about the CAN chips.
226  * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
227  * "sja1000".
228  * The @chip_base_addr entry represents the start of the 'official' memory map
229  * of the installed chip. It's likely that this is the same as the @io_addr
230  * argument supplied at module loading time.
231  * The @clock entry holds the chip clock value in Hz.
232  * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
233  * register. Options defined in the %sja1000.h file:
234  * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
235  * The entry @sja_ocr_reg holds hardware specific options for the Output Control
236  * register. Options defined in the %sja1000.h file:
237  * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
238  * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
239  * The entry @int_clk_reg holds hardware specific options for the Clock Out
240  * register. Options defined in the %i82527.h file:
241  * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
242  * The entry @int_bus_reg holds hardware specific options for the Bus
243  * Configuration register. Options defined in the %i82527.h file:
244  * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
245  * The entry @int_cpu_reg holds hardware specific options for the cpu interface
246  * register. Options defined in the %i82527.h file:
247  * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
248  * Return Value: The function always returns zero
249  * File: src/m437.c
250  */
251 int m437_init_chip_data(struct candevice_t *candev, int chipnr)
252 {
253         i82527_fill_chipspecops(candev->chip[chipnr]);
254         candev->chip[chipnr]->chip_base_addr=candev->dev_base_addr;
255         candev->chip[chipnr]->clock = 16000000;
256         candev->chip[chipnr]->int_cpu_reg = iCPU_DSC | iCPU_CEN;
257         candev->chip[chipnr]->int_clk_reg =
258                 iCLK_CD0 | iCLK_CD1 | iCLK_CD2 | iCLK_SL0 | iCLK_SL1;
259         candev->chip[chipnr]->int_bus_reg = iBUS_CBY;
260
261         return 0;
262 }
263
264 /**
265  * m437_init_obj_data - Initialize message buffers
266  * @chip: Pointer to chip specific structure
267  * @objnr: Number of the message buffer
268  *
269  * The function m437_init_obj_data() is used to initialize the hardware
270  * structure containing information about the different message objects on the
271  * CAN chip. In case of the sja1000 there's only one message object but on the
272  * i82527 chip there are 15.
273  * The code below is for a i82527 chip and initializes the object base addresses
274  * The entry @obj_base_addr represents the first memory address of the message
275  * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
276  * base address.
277  * Unless the hardware uses a segmented memory map, flags can be set zero.
278  * Return Value: The function always returns zero
279  * File: src/m437.c
280  */
281 int m437_init_obj_data(struct canchip_t *chip, int objnr)
282 {
283         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr+(objnr+1)*0x10;
284
285         return 0;
286 }
287
288 /**
289  * m437_program_irq - program interrupts
290  * @candev: Pointer to candevice/board structure
291  *
292  * The function m437_program_irq() is used for hardware that uses
293  * programmable interrupts. If your hardware doesn't use programmable interrupts
294  * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and
295  * leave this function unedited. Again this function is hardware specific so
296  * there's no example code.
297  * Return value: The function returns zero on success or %-ENODEV on failure
298  * File: src/m437.c
299  */
300 int m437_program_irq(struct candevice_t *candev)
301 {
302         DEBUGMSG("M437 Programmable interrupt is not supported by the hardware!\n");
303         return 0;
304 }
305
306 /**
307  * m437_write_register - Low level write register routine
308  * @data: data to be written
309  * @address: memory address to write to
310  *
311  * The function m437_write_register() is used to write to hardware registers
312  * on the CAN chip. You should only have to edit this function if your hardware
313  * uses some specific write process.
314  * Return Value: The function does not return a value
315  * File: src/m437.c
316  */
317 void m437_write_register(unsigned data, can_ioptr_t address)
318 {
319         DEBUGMSG("m437_write_register(@0x%lx=0x%x)\n", address, data);
320         can_writeb(data,address);
321 }
322
323 /**
324  * m437_read_register - Low level read register routine
325  * @address: memory address to read from
326  *
327  * The function m437_read_register() is used to read from hardware registers
328  * on the CAN chip. You should only have to edit this function if your hardware
329  * uses some specific read process.
330  * Return Value: The function returns the value stored in @address
331  * File: src/m437.c
332  */
333 unsigned m437_read_register(can_ioptr_t address)
334 {
335         unsigned data;
336         data = can_readb(address);
337         DEBUGMSG("m437_read_register(@0x%lx=0x%x)\n", address, data);
338         return data;
339 }
340
341 /* !!! Don't change this function !!! */
342 int m437_register(struct hwspecops_t *hwspecops)
343 {
344         DEBUGMSG("m437_register()\n");
345         hwspecops->request_io = m437_request_io;
346         hwspecops->release_io = m437_release_io;
347         hwspecops->reset = m437_reset;
348         hwspecops->init_hw_data = m437_init_hw_data;
349         hwspecops->init_chip_data = m437_init_chip_data;
350         hwspecops->init_obj_data = m437_init_obj_data;
351         hwspecops->write_register = m437_write_register;
352         hwspecops->read_register = m437_read_register;
353         hwspecops->program_irq = m437_program_irq;
354         return 0;
355 }