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