]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/hms30c7202_can.c
The LinCAN driver license unified according to DCE FEE CTU head and superiors request.
[lincan.git] / lincan / src / hms30c7202_can.c
1 /**************************************************************************/
2 /* File: hms30c7202_can.c - Hynix HMS30c7202 ARM integrated C_CAN handling*/
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) 2004 Sebastian Stolzenberg <stolzi@sebastian-stolzenberg.de> */
8 /* Funded by OCERA and FRESCOR IST projects                               */
9 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl>      */
10 /* and Ake Hedman, eurosource <akhe@eurosource.se>                        */
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 #include <linux/delay.h>
38
39 #include "../include/can.h"
40 #include "../include/can_sysdep.h"
41 #include "../include/main.h"
42 #include "../include/c_can.h"
43 #include "../include/hms30c7202_can.h"
44
45 /*
46  * IO_RANGE is the io-memory range that gets reserved, please adjust according
47  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
48  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
49  */
50 #define IO_RANGE 0x17E
51
52 /**
53  * hms30c7202_request_io: - reserve io or memory range for can board
54  * @candev: pointer to candevice/board which asks for io. Field @io_addr
55  *      of @candev is used in most cases to define start of the range
56  *
57  * The function hms30c7202_request_io() is used to reserve the io-memory. If your
58  * hardware uses a dedicated memory range as hardware control registers you
59  * will have to add the code to reserve this memory as well. 
60  * %IO_RANGE is the io-memory range that gets reserved, please adjust according
61  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
62  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
63  * Return Value: The function returns zero on success or %-ENODEV on failure
64  * File: src/template.c
65  */
66 int hms30c7202_request_io(struct candevice_t *candev)
67 {
68         DEBUGMSG("(c%d)calling hms30c7202_request_io(...)\n", candev->chip[0]->chip_idx);
69
70         if(!can_request_mem_region(candev->io_addr, IO_RANGE, DEVICE_NAME )) {
71                 CANMSG("hmsc30c7202_can failed to request mem region %lx.\n",
72                 (unsigned long)candev->io_addr );
73         }
74         
75         if (!( candev->dev_base_addr = ioremap( candev->io_addr, IO_RANGE ))) {
76                 DEBUGMSG( "Failed to map IO-memory: 0x%lx - 0x%lx, mapped to 0x%lx\n",
77                         (unsigned long)candev->io_addr,
78                         (unsigned long)candev->io_addr + IO_RANGE - 1,
79                         (unsigned long)candev->dev_base_addr);
80                 can_release_mem_region(candev->io_addr, IO_RANGE);
81                 return -ENODEV;
82         } else {
83         
84                 DEBUGMSG( "Mapped IO-memory: 0x%lx - 0x%lx, mapped to 0x%lx\n",
85                         (unsigned long)candev->io_addr,
86                         (unsigned long)candev->io_addr + IO_RANGE - 1,
87                         (unsigned long)candev->dev_base_addr);
88         
89         }
90         
91         candev->chip[0]->chip_base_addr=candev->dev_base_addr;
92         
93         //pchip->write_register(0, pchip->vbase_addr + CCCR);
94         //DEBUGMSG("C-CAN Control Register : 0x%.4lx\n",
95         //      (unsigned long)(c_can_read_reg_w( pchip->vbase_addr + CCCR)));
96         candev->chip[0]->chipspecops->start_chip(candev->chip[0]);
97         //DEBUGMSG("C-CAN Control Register : 0x%.4lx\n",
98         //      (unsigned long)(c_can_read_reg_w( pchip->vbase_addr + CCCR)));
99         
100         //DEBUGMSG("hms30c7202_can request i/o, leaving.\n");
101         return 0;
102 }
103
104
105 /**
106  * hms30c7202_release_io - free reserved io memory range
107  * @candev: pointer to candevice/board which releases io
108  *
109  * The function hms30c7202_release_io() is used to free reserved io-memory.
110  * In case you have reserved more io memory, don't forget to free it here.
111  * IO_RANGE is the io-memory range that gets released, please adjust according
112  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
113  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
114  * Return Value: The function always returns zero
115  * File: src/template.c
116  */
117 int hms30c7202_release_io(struct candevice_t *candev)
118 {
119         u16 tempReg;
120         
121         //disable IRQ generation
122         tempReg = c_can_read_reg_w(candev->chip[0], CCCR);
123
124         c_can_config_irqs(candev->chip[0], 0);
125         
126         /*  // clear all message objects
127         for (i=1; i<=15; i++) {
128         ccscan_write_register(
129                         INTPD_RES |
130                         RXIE_RES |
131                         TXIE_RES |
132                         MVAL_RES,
133                         pchip->vbase_addr +
134                         i*0x10 + iMSGCTL0 );
135         ccscan_write_register(
136                         NEWD_RES |
137                         MLST_RES |
138                         CPUU_RES |
139                         TXRQ_RES |
140                         RMPD_RES,
141                         pchip->vbase_addr +
142                         i*0x10 + iMSGCTL1 );
143         }
144         */
145         // power down HMS30c7202 - C_CAN
146         candev->chip[0]->chipspecops->stop_chip(candev->chip[0]);
147         
148         // release I/O memory mapping
149         iounmap(candev->dev_base_addr);
150         
151         // Release the memory region
152         can_release_mem_region(candev->io_addr, IO_RANGE);
153         
154         return 0;
155 }
156
157 /**
158  * hms30c7202_reset - hardware reset routine
159  * @card: Number of the hardware card.
160  *
161  * The function hms30c7202_reset() is used to give a hardware reset. This is
162  * rather hardware specific so I haven't included example code. Don't forget to
163  * check the reset status of the chip before returning.
164  * Return Value: The function returns zero on success or %-ENODEV on failure
165  * File: src/template.c
166  */
167 int hms30c7202_reset(  struct candevice_t *candev)
168 {
169         int i=0;
170         int enableTest=0, disableTest=0;
171         struct canchip_t *pchip = candev->chip[0];
172         
173         enableTest = pchip->chipspecops->enable_configuration(pchip);
174         disableTest = pchip->chipspecops->disable_configuration(pchip);
175         if( enableTest || disableTest) {
176                 CANMSG("Reset status timeout!\n");
177                 CANMSG("Please check your hardware.\n");
178                 return -ENODEV;
179         }
180         
181         /* Check busoff status */
182         
183         while ( (c_can_read_reg_w(pchip, CCSR) & SR_BOFF) && (i<=15)) {
184                 udelay(20000);
185                 i++;
186         }
187         if (i>=15) {
188                 CANMSG("Reset status timeout!\n");
189                 CANMSG("Please check your hardware.\n");
190                 return -ENODEV;
191         }
192         else
193                 DEBUGMSG("Chip0 reset status ok.\n");
194         
195         //pchip->config_irqs(pchip, CR_MIE | CR_SIE | CR_EIE);
196         return 0;
197 }
198
199 #define RESET_ADDR 0x0
200 #define NR_C_CAN 1
201 #define NR_MSGOBJ 32
202
203 /**
204  * hms30c7202_init_hw_data - Initialize hardware cards
205  * @candev: Pointer to candevice/board structure
206  *
207  * The function hms30c7202_init_hw_data() is used to initialize the hardware
208  * structure containing information about the installed CAN-board.
209  * %RESET_ADDR represents the io-address of the hardware reset register.
210  * %NR_82527 represents the number of intel 82527 chips on the board.
211  * %NR_SJA1000 represents the number of philips sja1000 chips on the board.
212  * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
213  * the hardware uses programmable interrupts.
214  * Return Value: The function always returns zero
215  * File: src/template.c
216  */
217 int hms30c7202_init_hw_data(struct candevice_t *candev) 
218 /*( struct canchip_t *pchip, u16 chip_nr, u16 startminor, u32 baseaddr, u8 irq )*/
219 {
220         //      u32 intCntrVAddr = 0;
221         can_ioptr_t gpioVAddr = 0;
222         u32 tempReg = 0;
223         u32 baseaddr=candev->io_addr;
224         
225         //      if ( (!( intCntrVAddr = ioremap( 0x80024000, 0xCD ) ))
226         //              & (! ( gpioVAddr = ioremap( 0x80023000, 0xAD ) ))) {
227         //              DEBUGMSG("Failed to map Int and GPIO memory\n");
228         //              return -EIO;
229         //      }
230         if ( ! ( gpioVAddr = ioremap( 0x80023000, 0xAD ) )) {
231                 DEBUGMSG("Failed to map GPIO memory\n");
232                 return -EIO;
233         } else {
234         
235                 //   DEBUGMSG( "Mapped Interrupt Controller IO-memory: 0x%lx - 0x%lx to 0x%lx\n",
236                 //            (unsigned long)0X80024000,
237                 //            (unsigned long)0X800240CC,
238                 //            (unsigned long)intCntrVAddr);
239                 DEBUGMSG( "Mapped GPIO IO-memory: 0x%lx - 0x%lx to 0x%lx\n",
240                         (unsigned long)0X80023000,
241                         (unsigned long)0X800240AC,
242                         (unsigned long)gpioVAddr);
243         }
244         
245         if (baseaddr == 0x8002f000) {
246                 //              tempReg = can_readl(intCntrVAddr);
247                 //              DEBUGMSG("Read Interrupt Enable Register : 0x%.4lx\n",(long)tempReg);
248                 //              DEBUGMSG("Trying to activate CAN0 Interrupt (Bit 18)\n");
249                 //              can_writel((tempReg | (1<<18)), intCntrVAddr);
250                 //              tempReg = can_readl(intCntrVAddr);
251                 //              DEBUGMSG("Read changed Interrupt Enable Register : 0x%.4lx\n",(long)tempReg);
252                 tempReg = can_readl(gpioVAddr + 0x5C);
253                 DEBUGMSG("Read GPIO-C Enable Register : 0x%.4lx\n",(long)tempReg);
254                 DEBUGMSG("Trying to activate CAN0 (Bit 1 = 0 for CANTx0, Bit 2 = 0 for CANRx0,)\n");
255                 can_writel(tempReg & ~0x6, gpioVAddr + 0x5C);
256                 tempReg = can_readl(gpioVAddr + 0x5C);
257                 DEBUGMSG("Read changed GPIO-C Enable Register : 0x%.4lx\n",(long)tempReg);
258                 tempReg = can_readl(gpioVAddr + 0x44);
259                 DEBUGMSG("Read GPIO-C Direction Register : 0x%.4lx\n",(long)tempReg);
260                 DEBUGMSG("Trying to set CAN0 directions (Bit 1 = 0 for CANTx0 as OUT, Bit 2 = 1 for CANRx0 as IN,)\n");
261                 can_writel((tempReg & ~0x2) | 0x4, gpioVAddr + 0x44);
262                 tempReg = can_readl(gpioVAddr + 0x44);
263                 DEBUGMSG("Read changed GPIO-C Direction Register : 0x%.4lx\n",(long)tempReg);
264         }
265         else if (baseaddr == 0x80030000) {
266                 //              tempReg = can_readl(intCntrVAddr);
267                 //              can_writel((tempReg | (1<<19)), intCntrVAddr);
268                 tempReg = can_readl(gpioVAddr + 0x9C);
269                 DEBUGMSG("Read GPIO-E Enable Register : 0x%.8lx\n",(long)tempReg);
270                 DEBUGMSG("Trying to activate CAN1 (Bit 22 = 0 for CANRx1, Bit 23 = 0 for CANTx1,)\n");
271                 can_writel(tempReg & 0xFF3FFFFF, gpioVAddr + 0x9C);
272                 tempReg = can_readl(gpioVAddr + 0x9C);
273                 DEBUGMSG("Read changed GPIO-E Enable Register : 0x%.8lx\n",(long)tempReg);
274                 tempReg = can_readl(gpioVAddr + 0x84);
275                 DEBUGMSG("Read GPIO-E Direction Register : 0x%.8lx\n",(long)tempReg);
276                 DEBUGMSG("Trying to set CAN1 directions (Bit 22 = 1 for CANRx1 as IN, Bit 23 = 0 for CANTx1 as OUT,)\n");
277                 can_writel((tempReg & ~(1<<23)) | 1<<22, gpioVAddr + 0x84);
278                 tempReg = can_readl(gpioVAddr + 0x84);
279                 DEBUGMSG("Read changed GPIO-E Direction Register : 0x%.8lx\n",(long)tempReg);
280         }
281
282         //DEBUGMSG("Current Interrupt Status Register (ISR): 0x%4.4lx\n",
283         //                      (long)can_readl(intCntrVAddr + 4));
284         //DEBUGMSG("Current Interrupt ID: %d\n",
285         //                      (int)(can_readl(intCntrVAddr + 0x90) & 0xF));
286         //      iounmap( (void*)intCntrVAddr);
287         iounmap( gpioVAddr );
288         //      DEBUGMSG( "Unmapped Interrupt Controller IO-memory: 0x%lx\n",
289         //            (unsigned long)intCntrVAddr);
290         DEBUGMSG( "Unmapped GPIO IO-memory: 0x%lx\n",
291                 (unsigned long)gpioVAddr);
292
293         // Initialize chip data ( only one chip )
294         //  pcandev->pchip[ 0 ]->powner = pcandev;
295         /*pchip->ntype = CAN_CHIPTYPE_C_CAN;*/
296         
297         candev->nr_82527_chips=0;
298         candev->nr_sja1000_chips=0;
299         candev->nr_all_chips=NR_C_CAN;
300
301         return 0;
302 }
303
304
305 #define CHIP_TYPE "c_can"
306 /**
307  * hms30c7202_init_chip_data - Initialize chips
308  * @candev: Pointer to candevice/board structure
309  * @chipnr: Number of the CAN chip on the hardware card
310  *
311  * The function hms30c7202_init_chip_data() is used to initialize the hardware
312  * structure containing information about the CAN chips.
313  * %CHIP_TYPE represents the type of CAN chip.
314  * The @chip_base_addr entry represents the start of the 'official' memory map
315  * of the installed chip. It's likely that this is the same as the @io_addr
316  * argument supplied at module loading time.
317  * The @clock entry holds the chip clock value in Hz.
318  * File: src/template.c
319  */
320 int hms30c7202_init_chip_data(struct candevice_t *candev, int chipnr)
321 {
322         // Register chip operations
323         c_can_fill_chipspecops(candev->chip[chipnr]);
324         /* override chip provided default value */
325         candev->chip[chipnr]->max_objects = NR_MSGOBJ;
326
327         candev->chip[chipnr]->chip_base_addr=candev->io_addr;
328         
329         candev->chip[chipnr]->clock = 16000000/2;
330         
331         /*candev->chip[chipnr]->int_clk_reg = 0x0;
332         candev->chip[chipnr]->int_bus_reg = 0x0;
333         candev->chip[chipnr]->sja_cdr_reg = 0x0;
334         candev->chip[chipnr]->sja_ocr_reg = 0x0;*/
335         
336
337         return 0;
338 }
339
340
341 /**
342  * hms30c7202_init_obj_data - Initialize message buffers
343  * @chip: Pointer to chip specific structure
344  * @objnr: Number of the message buffer
345  *
346  * The function hms30c7202_init_obj_data() is used to initialize the hardware
347  * structure containing information about the different message objects on the
348  * CAN chip. 
349  * The entry @obj_base_addr represents the first memory address of the message 
350  * object. 
351  * Unless the hardware uses a segmented memory map, flags can be set zero.
352  * Return Value: The function always returns zero
353  * File: src/template.c
354  */
355 int hms30c7202_init_obj_data(struct canchip_t *chip, int objnr)
356 {
357
358         DEBUGMSG("(c%d)calling hms30c7202_init_obj_data( ...)\n", chip->chip_idx);
359
360         /* It seems, that there is no purpose to setup object base address */
361         chip->msgobj[objnr]->obj_base_addr=0;
362         
363         /*can_msgobj_test_fl(pmsgobj,RX_MODE_EXT);*/
364         return 0;
365 }
366
367 /**
368  * hms30c7202_write_register - Low level write register routine
369  * @data: data to be written
370  * @address: memory address to write to
371  *
372  * The function hms30c7202_write_register() is used to write to hardware registers
373  * on the CAN chip. The registers are mapped on 32 bit bus on hms30c7202
374  * and thus registers span is twice as one defined by C_CAN manual and defines.
375  * This function compensates this difference.
376  * Return Value: The function does not return a value
377  * File: src/template.c
378  */
379
380 void hms30c7202_write_register(unsigned data, can_ioptr_t address)
381 {
382         unsigned long addr=can_ioptr2ulong(address);
383         int i;
384         //unsigned long usecs = 1;
385
386         address = can_ulong2ioptr(((addr & C_CAN_REGOFFS_MASK) << 1) |
387                                   (addr & ~C_CAN_REGOFFS_MASK));
388         
389         //DEBUGMSG("Trying to write 0x%u16x to address 0x%lx\n",data,address);
390         
391         can_writew(data,address);
392         //udelay( usecs );
393         for (i=0; i<5; i++);
394 }
395
396 /**
397  * hms30c7202_read_register - Low level read register routine
398  * @address: memory address to read from
399  *
400  * The function hms30c7202_read_register() is used to read from hardware registers
401  * on the CAN chip. The registers are mapped on 32 bit bus on hms30c7202
402  * and thus registers span is twice as one defined by C_CAN manual and defines.
403  * This function compensates this difference.
404  * Return Value: The function returns the value stored in @address
405  * File: src/template.c
406  */
407 unsigned hms30c7202_read_register(can_ioptr_t address)
408 {
409         unsigned long addr=can_ioptr2ulong(address);
410         u16 value, i;
411         
412         address = can_ulong2ioptr(((addr & C_CAN_REGOFFS_MASK) << 1) |
413                                   (addr & ~C_CAN_REGOFFS_MASK));
414
415         //DEBUGMSG("Trying to read from address 0x%lx :",address);
416         
417         value = can_readw(address);
418         //udelay( usecs );
419         for (i=0;i<5;i++);
420         value = can_readw(address);
421                 //udelay( usecs );
422         for (i=0;i<5;i++);
423         
424         //DEBUGMSG("0x%u16x\n",value);
425         return value;
426
427 }
428
429 /**
430  * hms30c7202_program_irq - program interrupts
431  * @candev: Pointer to candevice/board structure
432  *
433  * The function hms30c7202_program_irq() is used for hardware that uses 
434  * programmable interrupts. If your hardware doesn't use programmable interrupts
435  * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and 
436  * leave this function unedited. Again this function is hardware specific so 
437  * there's no example code.
438  * Return value: The function returns zero on success or %-ENODEV on failure
439  * File: src/template.c
440  */
441 int hms30c7202_program_irq(struct candevice_t *candev)
442 {
443         return 0;
444 }
445
446 int hms30c7202_register(struct hwspecops_t *hwspecops)
447 {
448         hwspecops->request_io = hms30c7202_request_io;
449         hwspecops->release_io = hms30c7202_release_io;
450         hwspecops->reset = hms30c7202_reset;
451         hwspecops->init_hw_data = hms30c7202_init_hw_data;
452         hwspecops->init_chip_data = hms30c7202_init_chip_data;
453         hwspecops->init_obj_data = hms30c7202_init_obj_data;
454         hwspecops->write_register = hms30c7202_write_register;
455         hwspecops->read_register = hms30c7202_read_register;
456         hwspecops->program_irq = hms30c7202_program_irq;
457         return 0;
458 }
459