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