]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/omap2_spican.c
Fix for omap2 specific code
[lincan.git] / lincan / src / omap2_spican.c
1 /* omap2_spican.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
10 #include <linux/err.h>
11 #include <linux/errno.h>
12 #include <linux/mutex.h>
13 #include <linux/irq.h>
14 #include <linux/interrupt.h>
15 #include <linux/types.h>
16 #include <linux/proc_fs.h>
17 #include <linux/clk.h>          
18 #include <linux/spi/spi.h>
19
20 #include "../include/can.h"
21 #include "../include/can_sysdep.h"
22 #include "../include/main.h"
23 #include "../include/setup.h"
24 #include "../include/omap2_spican.h"
25 #include "../include/mcp2515.h"
26
27 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
28         #include <asm/io.h>                     
29         #include <asm/uaccess.h>
30         #include <plat/dmtimer.h>       
31 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
32
33 static const char* omap2_spican_defaulttype = "mcp2515";
34
35 static struct workqueue_struct *omap2_spican_wq;
36
37 /*******************************************************************/
38 /*
39  * We can't use the standard synchronous wrappers for file I/O; we
40  * need to protect against async removal of the underlying spi_device.
41  */
42 static void omap2_spican_spi_complete(void *arg)
43 {
44         DEBUGMSG("SPICAN sync: complete\n");
45         complete(arg);
46 }
47
48 ssize_t omap2_spican_spi_sync(struct candevice_t *candev, struct spi_message *message)
49 {
50         DECLARE_COMPLETION_ONSTACK(done);
51         struct omap2_spican_platform_data *pdata;
52         int status;
53         
54         if (candev == NULL)
55                 return -ESHUTDOWN;
56         if (message == NULL)
57                 panic("SPICAN: trying to send null pointered message");
58
59         pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
60         if (pdata == NULL)
61                 return -ESHUTDOWN;
62
63         message->complete = omap2_spican_spi_complete;
64         message->context = &done;
65         spin_lock_irq(&pdata->spi_lock);
66         if (pdata->spi == NULL)
67                 status = -ESHUTDOWN;
68         else{
69                 DEBUGMSG("SPICAN sync: transfer\n");
70                 status = spi_async(pdata->spi, message);
71         }
72         spin_unlock_irq(&pdata->spi_lock);
73
74         if (status == 0) {
75                 while (!wait_for_completion_interruptible_timeout(&done, msecs_to_jiffies(10))) { 
76                         DEBUGMSG("SPICAN sync: timeout 10 msecs\n");
77                 }
78 //              do { ;} while (wait_for_completion_interruptible(&done));
79                 status = message->status;
80                 if (status == 0)
81                         status = message->actual_length;
82         }
83         return status;
84 }
85
86 static ssize_t omap2_spican_spi_transfer(struct candevice_t *candev,void *tx, void *rx, uint16_t len)
87 {
88         struct omap2_spican_platform_data *pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
89         struct spi_transfer     t = {
90                 .tx_buf         = tx,
91                 .rx_buf         = rx,
92                 .len            = len,
93                 .cs_change = 1,
94                 .speed_hz = pdata->speed_hz,
95                 .bits_per_word = 8,
96         };
97         struct spi_message      m;
98         int i,status;
99
100         if (pdata == NULL)
101                 return -1;
102         if(len > SPI_BUF_LEN) panic("long CAN spi transfer: %u",len);
103
104         spi_message_init(&m);
105
106         spi_message_add_tail(&t, &m);
107         status = omap2_spican_spi_sync(candev, &m);
108         return status;
109 }
110
111 static void hi_async_tasklet_handler(unsigned long data)
112 {
113         struct omap2_spican_platform_data *pdata=(struct omap2_spican_platform_data *)data;
114         int n;
115         
116         if (pdata == NULL)
117                 return;
118
119         
120         do {
121                 n = find_first_bit(pdata->hi_async_done_map,OMAP2_SPICAN_PRE_ASYNC);
122                 if (n == OMAP2_SPICAN_PRE_ASYNC)
123                         break;
124
125                 DEBUGMSG("SPICAN async %d: high priority tasklet\n",n);
126                 if (pdata->async[n].complete)
127                         pdata->async[n].complete(pdata->async[n].data,pdata->async[n].count);
128                 
129                 clear_bit(n,pdata->hi_async_done_map);
130                 clear_bit(n,pdata->async_req_map);
131         } while (n < OMAP2_SPICAN_PRE_ASYNC);
132 }
133
134 static void lo_async_workqueue_handler(struct work_struct *work)
135 {
136         struct omap2_spican_platform_data *pdata = container_of(work,struct omap2_spican_platform_data,lo_async_workqueue);
137         struct omap2_spican_async_t *async;
138         int n;
139
140         if (pdata == NULL)
141                 return;
142
143         do {
144                 n = find_first_bit(pdata->lo_async_done_map,OMAP2_SPICAN_PRE_ASYNC);
145                 if (n >= OMAP2_SPICAN_PRE_ASYNC)
146                         break;
147
148                 DEBUGMSG("SPICAN async %d: low priority workqueue\n",n);
149                 async = pdata->async + n;
150
151                 if (async->complete)
152                         async->complete(async->data,async->count);
153                 
154                 clear_bit(n,pdata->lo_async_done_map);
155                 clear_bit(n,pdata->async_req_map);
156         } while (n < OMAP2_SPICAN_PRE_ASYNC);
157 }
158
159 static void omap2_spican_spi_async_complete(void *arg)
160 {
161         struct omap2_spican_async_t *as = (struct omap2_spican_async_t *)arg;
162         struct omap2_spican_platform_data *pdata = container_of(as,struct omap2_spican_platform_data,async[as->bitmap_bit]);
163         int i;
164
165 //      DEBUGMSG("SPICAN async: complete\n");
166         for (i=1;i<as->count;i++)
167                 can_filltimestamp(&as->data[i].timestamp);              
168         // Serve the fast handlers ASAP
169         if ((as->fasthandler) && (as->complete)){
170 //              DEBUGMSG("SPICAN async: fasthandler\n");
171 /*              set_bit(as->bitmap_bit,pdata->hi_async_done_map);
172                 tasklet_hi_schedule(&pdata->hi_async_tasklet);*/
173                 if (as->complete){
174                         as->complete(as->data,as->count);
175                 }
176                 clear_bit(as->bitmap_bit,pdata->lo_async_done_map);
177                 clear_bit(as->bitmap_bit,pdata->async_req_map);
178 //              DEBUGMSG("SPICAN async: fasthandler done\n");
179                 return;
180         }
181         
182         DEBUGMSG("SPICAN async %d: slowhandler register\n",as->bitmap_bit);
183         set_bit(as->bitmap_bit,pdata->lo_async_done_map);
184         queue_work(omap2_spican_wq,&pdata->lo_async_workqueue);
185 }
186
187 ssize_t omap2_spican_spi_async_transfer(struct candevice_t *candev, void (*callback)(void *data), struct can_spi_async_t *data, uint8_t count, uint8_t fasthandler)
188 {
189         struct omap2_spican_platform_data *pdata;
190         struct omap2_spican_async_t *async;
191         int status,i;
192         int n;
193         
194         if (candev == NULL)
195                 return -ESHUTDOWN;
196
197         pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
198         if (pdata == NULL)
199                 return -ESHUTDOWN;
200         
201         if (count > OMAP2_SPICAN_MAX_TRANSFERS)
202                 return -ENOBUFS;
203
204         do {
205                 n = find_first_zero_bit(pdata->async_req_map, OMAP2_SPICAN_PRE_ASYNC);
206                 // There's no free transfer slot
207                 if (n == OMAP2_SPICAN_PRE_ASYNC)
208                         return -ENOBUFS;
209         } while (test_and_set_bit(n,pdata->async_req_map));
210         
211         async = pdata->async+n;
212
213         memset(async,0,sizeof(struct omap2_spican_async_t));
214
215         for (i=0;i<count;i++){
216                 if(data[i].len > SPI_MESSAGE_LENGTH)
217                         panic("too long CAN spi transfer: %u",data[i].len);
218         }
219
220         memcpy(async->data,data,count*sizeof(struct can_spi_async_t));
221         async->count = count;
222         async->bitmap_bit = n;
223         async->complete = callback;
224         async->fasthandler = fasthandler;
225
226         spi_message_init(&async->m);
227         
228         for (i=0;i<count;i++){
229                 if ((async->data[i].tx_buf == NULL) && (async->data[i].rx_buf == NULL) && async->data[i].len != 0)
230                         panic("Trying to send NULL pointered buffers");
231                 
232                 async->t[i].tx_buf = async->data[i].tx_buf;
233                 async->t[i].rx_buf = async->data[i].rx_buf;
234                 async->t[i].len = async->data[i].len;
235                 async->t[i].cs_change = 1;
236                 async->t[i].speed_hz = pdata->speed_hz;
237                 async->t[i].bits_per_word = 8;
238
239                 spi_message_add_tail(&async->t[i], &async->m);
240         }
241         
242         async->m.complete = omap2_spican_spi_async_complete;
243         async->m.context = async;
244         spin_lock_irq(&pdata->spi_lock);
245         if (pdata->spi == NULL)
246                 status = -ESHUTDOWN;
247         else{
248                 DEBUGMSG("SPICAN async %d: transfer\n",n);
249                 status = spi_async(pdata->spi, &async->m);
250         }
251         spin_unlock_irq(&pdata->spi_lock);
252         
253         if (status){
254                 clear_bit(n,pdata->async_req_map);
255         }
256
257         return status;
258 }
259
260 /**
261  * omap2_spican_irq_handler: - GPT (general purpose timer) and waiting
262  * thread interrupt handler
263  * @irq: the interrupt line number
264  * @dev_id: pointer to can device data
265  * 
266  * Return Value: Interrupt handled status is returned
267  * File: src/omap2_spican.c
268  */
269 static irqreturn_t omap2_spican_irq_handler(int irq, void *dev_id)
270 {
271         struct candevice_t *candev = dev_id;
272         struct omap2_spican_platform_data *pdata;
273         unsigned long flags;
274         int i;
275         
276         if (!dev_id)
277                 return IRQ_NONE;
278         
279         pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
280         if (!pdata)
281                 return IRQ_NONE;
282         
283 /*      if (((pdata->trigger == OMAP2_SPICAN_TRIG_GPT) && (irq != pdata->timer_irq))
284                 || ((pdata->trigger == OMAP2_SPICAN_TRIG_IRQ) && (irq != pdata->irq))
285         )
286                 return IRQ_NONE;*/
287         #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
288         if ((irq != pdata->timer_irq) && (irq != pdata->irq))
289                         return IRQ_NONE;
290         #else
291         if (irq != pdata->irq)
292                 return IRQ_NONE;
293         #endif
294         
295         
296         DEBUGMSG("SPICAN: Got interrupt");
297         #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
298 //      if (pdata->trigger == OMAP2_SPICAN_TRIG_GPT){
299         if (irq == pdata->timer_irq){
300                 // reset the timer interrupt status
301                 omap_dm_timer_write_status(pdata->timer_ptr, OMAP_TIMER_INT_OVERFLOW);
302                 omap_dm_timer_read_status(pdata->timer_ptr); // YES, you really need to do this 'wasteful' read
303         }
304         #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
305  
306         for (i=0;i<candev->nr_all_chips;i++){
307                 if (candev->chip[i]->chipspecops->irq_handler)
308                         candev->chip[i]->chipspecops->irq_handler(irq, candev->chip[i]);
309         }
310
311         return IRQ_HANDLED;
312         
313 }
314  
315 /**
316  * omap2_spican_request_io: - reserve io or memory range for can board
317  * @candev: pointer to candevice/board which asks for io. Field @io_addr
318  *      of @candev is used in most cases to define start of the range
319  *
320  * The function omap2_spican_request_io() is used to reserve the io-memory. If your
321  * hardware uses a dedicated memory range as hardware control registers you
322  * will have to add the code to reserve this memory as well. 
323  * %IO_RANGE is the io-memory range that gets reserved, please adjust according
324  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
325  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
326  * Return Value: The function returns zero on success or %-ENODEV on failure
327  * File: src/omap2_spican.c
328  */
329 int omap2_spican_request_io(struct candevice_t *candev)
330 {
331         return 0;
332 }
333
334 /**
335  * omap2_spican_release_io - free reserved io memory range
336  * @candev: pointer to candevice/board which releases io
337  *
338  * The function omap2_spican_release_io() is used to free reserved io-memory.
339  * In case you have reserved more io memory, don't forget to free it here.
340  * IO_RANGE is the io-memory range that gets released, please adjust according
341  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
342  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
343  * Return Value: The function always returns zero
344  * File: src/omap2_spican.c
345  */
346 int omap2_spican_release_io(struct candevice_t *candev)
347 {
348         return 0;
349 }
350
351 /**
352  * omap2_spican_reset - hardware reset routine
353  * @candev: Pointer to candevice/board structure
354  *
355  * The function omap2_spican_reset() is used to give a hardware reset. This is 
356  * rather hardware specific so I haven't included example code. Don't forget to 
357  * check the reset status of the chip before returning.
358  * Return Value: The function returns zero on success or %-ENODEV on failure
359  * File: src/omap2_spican.c
360  */
361 int omap2_spican_reset(struct candevice_t *candev)
362 {
363         int i;
364         DEBUGMSG("Resetting all underlying chips\n");
365         for(i=0;i<OMAP2_SPICAN_NCHIPS;i++)
366                 (candev->chip[i]->chipspecops->reset_chip)(candev->chip[i]);
367
368         return 0;
369 }
370
371 /**
372  * omap2_spican_init_hw_data - Initialize hardware cards
373  * @candev: Pointer to candevice/board structure
374  *
375  * The function omap2_spican_init_hw_data() is used to initialize the hardware
376  * structure containing information about the installed CAN-board.
377  * %RESET_ADDR represents the io-address of the hardware reset register.
378  * %NR_82527 represents the number of Intel 82527 chips on the board.
379  * %NR_SJA1000 represents the number of Philips sja1000 chips on the board.
380  * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
381  * the hardware uses programmable interrupts.
382  * Return Value: The function always returns zero
383  * File: src/omap2_spican.c
384  */
385 int omap2_spican_init_hw_data(struct candevice_t *candev) 
386 {
387         candev->dev_base_addr = 0;
388         candev->nr_82527_chips = 0;
389         candev->nr_sja1000_chips = 0;
390         candev->nr_mcp2515_chips = OMAP2_SPICAN_NCHIPS;
391         candev->nr_all_chips = candev->nr_82527_chips + 
392                 candev->nr_sja1000_chips + 
393                 candev->nr_mcp2515_chips;
394         candev->flags &= ~CANDEV_PROGRAMMABLE_IRQ;
395
396         return 0;
397 }
398
399 /**
400  * omap2_spican_init_chip_data - Initialize chips
401  * @candev: Pointer to candevice/board structure
402  * @chipnr: Number of the CAN chip on the hardware card
403  *
404  * The function omap2_spican_init_chip_data() is used to initialize the hardware
405  * structure containing information about the CAN chips.
406  * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
407  * "sja1000".
408  * The @chip_base_addr entry represents the start of the 'official' memory map
409  * of the installed chip. It's likely that this is the same as the @io_addr
410  * argument supplied at module loading time.
411  * The @clock entry holds the chip clock value in Hz.
412  * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
413  * register. Options defined in the %sja1000.h file:
414  * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
415  * The entry @sja_ocr_reg holds hardware specific options for the Output Control
416  * register. Options defined in the %sja1000.h file:
417  * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
418  * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
419  * The entry @int_clk_reg holds hardware specific options for the Clock Out
420  * register. Options defined in the %i82527.h file:
421  * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
422  * The entry @int_bus_reg holds hardware specific options for the Bus 
423  * Configuration register. Options defined in the %i82527.h file:
424  * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
425  * The entry @int_cpu_reg holds hardware specific options for the cpu interface
426  * register. Options defined in the %i82527.h file:
427  * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
428  * Return Value: The function always returns zero
429  * File: src/omap2_spican.c
430  */
431 int omap2_spican_init_chip_data(struct candevice_t *candev, int chipnr)
432 {
433         if(chipnr >= OMAP2_SPICAN_NCHIPS || chipnr < 0) {
434                 CANMSG("Error: chipnr=%d\n",chipnr);
435                 return -ENODEV;
436         }
437         
438         mcp2515_fill_chipspecops(candev->chip[chipnr]);
439 /*      candev->chip[chipnr]->chip_base_addr = 0;
440         candev->chip[chipnr]->spi_channel = 2;*/
441         candev->chip[chipnr]->chip_data = can_checked_malloc(sizeof(MCP2515_PRIV));
442         if(candev->chip[chipnr]->chip_data == NULL) return -ENOMEM;
443         memset(candev->chip[chipnr]->chip_data,0,sizeof(MCP2515_PRIV));
444
445         return 0;
446 }
447
448 int omap2_spican_register_chip_data(struct canchip_t *ch,void *data){
449         struct omap2_spican_platform_data *pdata = (struct omap2_spican_platform_data *)data;
450         ch->clock = pdata->clk;
451         ch->baudrate = pdata->baudrate;
452         int ret = 0;
453         
454         ch->flags |= CHIP_IRQ_CUSTOM;
455 //      if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ){
456 //              ch->chip_irq = pdata->irq;
457 //      }
458
459         ret = ch->chipspecops->chip_config(ch);
460         if (ret){
461                 CANMSG("Error configuring chip.\n");
462         }
463         else
464                 ch->flags |= CHIP_CONFIGURED; 
465         return ret;
466 }
467
468 /**
469  * omap2_spican_init_obj_data - Initialize message buffers
470  * @chip: Pointer to chip specific structure
471  * @objnr: Number of the message buffer
472  *
473  * The function omap2_spican_init_obj_data() is used to initialize the hardware
474  * structure containing information about the different message objects on the
475  * CAN chip. In case of the sja1000 there's only one message object but on the
476  * i82527 chip there are 15.
477  * The code below is for a i82527 chip and initializes the object base addresses
478  * The entry @obj_base_addr represents the first memory address of the message 
479  * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
480  * base address.
481  * Unless the hardware uses a segmented memory map, flags can be set zero.
482  * Return Value: The function always returns zero
483  * File: src/omap2_spican.c
484  */
485 int omap2_spican_init_obj_data(struct canchip_t *chip, int objnr)
486 {
487         chip->msgobj[objnr]->obj_base_addr=0;
488         chip->msgobj[objnr]->obj_flags=0;
489         
490         return 0;
491 }
492
493 /**
494  * omap2_spican_write_register - Low level write register routine
495  * @data: data to be written
496  * @address: memory address to write to
497  *
498  * The function omap2_spican_write_register() is used to write to hardware registers
499  * on the CAN chip. You should only have to edit this function if your hardware
500  * uses some specific write process.
501  * Return Value: The function does not return a value
502  * File: src/omap2_spican.c
503  */
504 void omap2_spican_write_register(unsigned data, can_ioptr_t address)
505 {
506         panic("omap2_spican_write_register");
507 }
508
509 /**
510  * omap2_spican_read_register - Low level read register routine
511  * @address: memory address to read from
512  *
513  * The function omap2_spican_read_register() is used to read from hardware registers
514  * on the CAN chip. You should only have to edit this function if your hardware
515  * uses some specific read process.
516  * Return Value: The function returns the value stored in @address
517  * File: src/omap2_spican.c
518  */
519 unsigned omap2_spican_read_register(can_ioptr_t address)
520 {
521         panic("omap2_spican_read_register");
522         return 0;
523 }
524
525 /**
526  * omap2_spican_program_irq - program interrupts
527  * @candev: Pointer to candevice/board structure
528  *
529  * The function omap2_spican_program_irq() is used for hardware that uses 
530  * programmable interrupts. If your hardware doesn't use programmable interrupts
531  * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and 
532  * leave this function unedited. Again this function is hardware specific so 
533  * there's no example code.
534  * Return value: The function returns zero on success or %-ENODEV on failure
535  * File: src/omap2_spican.c
536  */
537 int omap2_spican_program_irq(struct candevice_t *candev)
538 {
539         return 0;
540 }
541
542 /*******************************************************************/
543 int omap2_spican_spi_acquire_bus(struct candevice_t *candev, short channel, int block){
544         /* Subsystem is always ready to accept messages */
545         return 1;
546 }
547
548 /*******************************************************************/
549 void omap2_spican_spi_release_bus(struct candevice_t *candev, short channel){
550         return;
551 }
552
553 int omap2_spican_register(struct hwspecops_t *hwspecops)
554 {
555         hwspecops->request_io = omap2_spican_request_io;
556         hwspecops->release_io = omap2_spican_release_io;
557         hwspecops->reset = omap2_spican_reset;
558         hwspecops->init_hw_data = omap2_spican_init_hw_data;
559         hwspecops->init_chip_data = omap2_spican_init_chip_data;
560         hwspecops->init_obj_data = omap2_spican_init_obj_data;
561         hwspecops->write_register = omap2_spican_write_register;
562         hwspecops->read_register = omap2_spican_read_register;
563         hwspecops->program_irq = omap2_spican_program_irq;
564
565         // SPI specific functions
566         hwspecops->spi_transfer = omap2_spican_spi_transfer;
567         hwspecops->spi_async_transfer = omap2_spican_spi_async_transfer;
568         hwspecops->spi_acquire_bus = omap2_spican_spi_acquire_bus;
569         hwspecops->spi_release_bus = omap2_spican_spi_release_bus;
570
571         return 0;
572 }
573
574 /*******************************************************************/
575
576 static int omap2_spican_probe(struct spi_device *spi)
577 {
578         struct lincan_spican_platform_data      *spidata = spi->dev.platform_data;
579         struct omap2_spican_platform_data *pdata;
580         struct candevice_t *dev;
581         int allocated = 0;
582         
583         DEBUGMSG("Starting probe for omap2_spican...\n");
584         
585         // Structure checks and initialization
586         pdata = (struct omap2_spican_platform_data *)can_checked_malloc(sizeof(struct omap2_spican_platform_data));
587         if (pdata)
588                 memset(pdata,0,sizeof(struct omap2_spican_platform_data));
589         else
590                 return -ENOMEM;
591         
592         if (spidata)
593                 memcpy(pdata,spidata,sizeof(struct lincan_spican_platform_data));
594         else{
595                 if (!pdata->cs_change) pdata->cs_change = OMAP2_SPICAN_CS_CHANGE;
596                 if (!pdata->delay_usecs) pdata->delay_usecs = OMAP2_SPICAN_DELAY_USECS;
597         }
598         if (!pdata->clk) pdata->clk = OMAP2_SPICAN_MCP_CLK;
599         if (!pdata->baudrate) pdata->baudrate = OMAP2_SPICAN_BAUDRATE;
600         if (!pdata->speed_hz) pdata->speed_hz = OMAP2_SPICAN_SPEED_HZ;
601         if (!pdata->chiptype) pdata->chiptype = omap2_spican_defaulttype;
602
603         spin_lock_init(&pdata->spi_lock);
604         pdata->spi = spi;
605         pdata->trigger = 0;
606
607  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
608         INIT_WORK(&pdata->lo_async_workqueue, 
609                   lo_async_workqueue_handler, 
610                   &pdata->lo_async_workqueue);
611  #else
612         INIT_WORK(&pdata->lo_async_workqueue, 
613                   lo_async_workqueue_handler);
614  #endif
615         tasklet_init(&pdata->hi_async_tasklet,
616                      hi_async_tasklet_handler, 
617                      (unsigned long)pdata);
618         
619         if (spi->irq) {
620                 DEBUGMSG("Interrupt line number %d provided.\n",spi->irq);
621                 pdata->trigger = OMAP2_SPICAN_TRIG_IRQ;
622                 pdata->irq = spi->irq;
623         }
624         else
625                 DEBUGMSG("no IRQ given, trying to find timers. Performance loss will be observed.\n");
626
627         /* Register device data in LinCAN - 1 chip, 2 msgobjs */
628         dev = register_hotplug_dev("omap2_spican",omap2_spican_register_chip_data,pdata);
629         if (!dev)
630                 goto release;
631
632         if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ) {
633                 int status = 0;
634                 DEBUGMSG("Requesting interrupt line %d.\n",spi->irq);
635                 status = set_irq_type(pdata->irq,IRQ_TYPE_EDGE_FALLING);
636                 if(status){
637                         CANMSG("Setting falling edge trigger on irq %d failed.\n", spi->irq);
638                         goto release;
639                 }
640                 status = request_irq(pdata->irq, omap2_spican_irq_handler, IRQF_DISABLED , "omap2_spican", dev);
641                 if(status){
642                         CANMSG("request_irq failed on irq %d\n", spi->irq);
643                         goto release;
644                 }
645         }
646 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
647 //      if (pdata->trigger == 0){
648         {
649                 struct clk *gt_fclk;
650                 uint32_t gt_rate;
651                 int status = 0;
652                 int prescaler = 0;
653
654                 DEBUGMSG("Setting up OMAP GPT\n");
655                 // Get the timer
656                 pdata->timer_ptr = omap_dm_timer_request();
657                 if(pdata->timer_ptr == NULL){
658                         CANMSG("No more gp timers available, bailing out\n");
659                         goto release;
660                 }
661                 
662                 // Initialize timer
663                 omap_dm_timer_set_source(pdata->timer_ptr, OMAP_TIMER_SRC_SYS_CLK); // We use the system clock 38.4 MHz
664                 
665                 omap_dm_timer_set_prescaler(pdata->timer_ptr, prescaler);               // Set prescaler to 2^(n+1)
666  
667                 // get clock rate in Hz
668                 gt_fclk = omap_dm_timer_get_fclk(pdata->timer_ptr);
669                 gt_rate = clk_get_rate(gt_fclk)/(1<<(prescaler+1));
670          
671                 // set preload, and autoreload
672                 // we set it to the clock rate in order to get 1 overflow every 1 msec
673                 omap_dm_timer_set_load(pdata->timer_ptr, 1, 0xFFFFFFFF - (uint32_t)(gt_rate / 1000));
674
675                 // Request for the irq
676                 pdata->timer_irq = omap_dm_timer_get_irq(pdata->timer_ptr);
677                 DEBUGMSG("Requesting irq %d for OMAP GPT\n", pdata->timer_irq);
678                 status = request_irq(pdata->timer_irq, omap2_spican_irq_handler, IRQF_DISABLED | IRQF_TIMER , "omap2_spican", dev);
679                 if(status){
680                         CANMSG("request_irq failed (on irq %d), bailing out\n", pdata->timer_irq);
681                   omap_dm_timer_free(pdata->timer_ptr);
682                         goto release;
683                 }
684
685                 // setup timer to trigger our IRQ on the overflow event
686                 omap_dm_timer_set_int_enable(pdata->timer_ptr, OMAP_TIMER_INT_OVERFLOW);
687 //              pdata->trigger = OMAP2_SPICAN_TRIG_GPT;
688         }
689 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
690
691         spi_set_drvdata(spi, dev);
692
693 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
694 //                      if (pdata->trigger == OMAP2_SPICAN_TRIG_GPT){
695         {
696                 // Everything's ready, let's roll!
697                 DEBUGMSG("Starting OMAP GPT\n");
698                 omap_dm_timer_start(pdata->timer_ptr);
699         }
700 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
701         DEBUGMSG("Device omap2_spican successfully configured. Have fun!\n");
702         return 0;
703         
704 release:
705         can_checked_free(pdata);
706         return -ENODEV;
707 }
708
709 static int omap2_spican_remove(struct spi_device *spi)
710 {
711         struct candevice_t *candev = spi_get_drvdata(spi);
712         struct omap2_spican_platform_data *pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
713
714         if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ){
715                 // release the IRQ handler
716                 free_irq(pdata->irq, candev);
717         }
718 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
719 //      if (pdata->trigger == OMAP2_SPICAN_TRIG_GPT){
720         {
721                 DEBUGMSG("Stopping OMAP GPT\n");
722                 omap_dm_timer_stop(pdata->timer_ptr);
723                 // release the IRQ handler
724                 free_irq(pdata->timer_irq, candev);
725           // release the timer
726           omap_dm_timer_free(pdata->timer_ptr);
727         }
728 #endif
729
730         DEBUGMSG("Removing omap2_spican from device structure...");
731         //      make sure ops on existing fds can abort cleanly
732         deregister_hotplug_dev(candev);
733         cleanup_hotplug_dev(candev);
734
735         spin_lock_irq(&pdata->spi_lock);
736         pdata->spi = NULL;
737         spi_set_drvdata(spi, NULL);
738 //      candev->sysdevptr.anydev = NULL;
739         spin_unlock_irq(&pdata->spi_lock);
740
741         DEBUGMSG("Kill tasklets.\n");
742         tasklet_kill(&pdata->hi_async_tasklet);
743
744         can_checked_free(pdata);
745         DEBUGMSG(" done.\n");
746
747         return 0;
748 }
749
750 static struct spi_driver omap2_spican_driver = {
751         .driver = {
752                 .name   = "omap2_spican",
753                 .owner  = THIS_MODULE,
754         },
755         .probe          = omap2_spican_probe,
756         .remove         = omap2_spican_remove,
757 /*      .suspend        = omap2_spican_suspend,
758         .resume         = omap2_spican_resume,*/
759 };
760
761 int omap2_spican_init(void){
762         omap2_spican_wq = create_singlethread_workqueue("omap2_spican");
763         if (omap2_spican_wq == NULL)
764                 return -1;
765         return spi_register_driver(&omap2_spican_driver);
766 }
767
768 void omap2_spican_exit(void){
769         spi_unregister_driver(&omap2_spican_driver);
770         destroy_workqueue(omap2_spican_wq);
771 }
772
773 #ifdef MODULE_ALIAS
774 MODULE_ALIAS("spi:omap2_spican");
775 #endif