]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/omap2_spican.c
Support for asynchronous SPI messages and callbacks
[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         if ((irq != pdata->timer_irq) && (irq != pdata->irq))
288                 return IRQ_NONE;
289         
290         DEBUGMSG("SPICAN: Got interrupt");
291         #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
292 //      if (pdata->trigger == OMAP2_SPICAN_TRIG_GPT){
293         if (irq == pdata->timer_irq){
294                 // reset the timer interrupt status
295                 omap_dm_timer_write_status(pdata->timer_ptr, OMAP_TIMER_INT_OVERFLOW);
296                 omap_dm_timer_read_status(pdata->timer_ptr); // YES, you really need to do this 'wasteful' read
297         }
298         #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
299  
300         for (i=0;i<candev->nr_all_chips;i++){
301                 if (candev->chip[i]->chipspecops->irq_handler)
302                         candev->chip[i]->chipspecops->irq_handler(irq, candev->chip[i]);
303         }
304
305         return IRQ_HANDLED;
306         
307 }
308  
309 /**
310  * omap2_spican_request_io: - reserve io or memory range for can board
311  * @candev: pointer to candevice/board which asks for io. Field @io_addr
312  *      of @candev is used in most cases to define start of the range
313  *
314  * The function omap2_spican_request_io() is used to reserve the io-memory. If your
315  * hardware uses a dedicated memory range as hardware control registers you
316  * will have to add the code to reserve this memory as well. 
317  * %IO_RANGE is the io-memory range that gets reserved, please adjust according
318  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
319  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
320  * Return Value: The function returns zero on success or %-ENODEV on failure
321  * File: src/omap2_spican.c
322  */
323 int omap2_spican_request_io(struct candevice_t *candev)
324 {
325         return 0;
326 }
327
328 /**
329  * omap2_spican_release_io - free reserved io memory range
330  * @candev: pointer to candevice/board which releases io
331  *
332  * The function omap2_spican_release_io() is used to free reserved io-memory.
333  * In case you have reserved more io memory, don't forget to free it here.
334  * IO_RANGE is the io-memory range that gets released, please adjust according
335  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
336  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
337  * Return Value: The function always returns zero
338  * File: src/omap2_spican.c
339  */
340 int omap2_spican_release_io(struct candevice_t *candev)
341 {
342         return 0;
343 }
344
345 /**
346  * omap2_spican_reset - hardware reset routine
347  * @candev: Pointer to candevice/board structure
348  *
349  * The function omap2_spican_reset() is used to give a hardware reset. This is 
350  * rather hardware specific so I haven't included example code. Don't forget to 
351  * check the reset status of the chip before returning.
352  * Return Value: The function returns zero on success or %-ENODEV on failure
353  * File: src/omap2_spican.c
354  */
355 int omap2_spican_reset(struct candevice_t *candev)
356 {
357         int i;
358         DEBUGMSG("Resetting all underlying chips\n");
359         for(i=0;i<OMAP2_SPICAN_NCHIPS;i++)
360                 (candev->chip[i]->chipspecops->reset_chip)(candev->chip[i]);
361
362         return 0;
363 }
364
365 /**
366  * omap2_spican_init_hw_data - Initialize hardware cards
367  * @candev: Pointer to candevice/board structure
368  *
369  * The function omap2_spican_init_hw_data() is used to initialize the hardware
370  * structure containing information about the installed CAN-board.
371  * %RESET_ADDR represents the io-address of the hardware reset register.
372  * %NR_82527 represents the number of Intel 82527 chips on the board.
373  * %NR_SJA1000 represents the number of Philips sja1000 chips on the board.
374  * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
375  * the hardware uses programmable interrupts.
376  * Return Value: The function always returns zero
377  * File: src/omap2_spican.c
378  */
379 int omap2_spican_init_hw_data(struct candevice_t *candev) 
380 {
381         candev->dev_base_addr = 0;
382         candev->nr_82527_chips = 0;
383         candev->nr_sja1000_chips = 0;
384         candev->nr_mcp2515_chips = OMAP2_SPICAN_NCHIPS;
385         candev->nr_all_chips = candev->nr_82527_chips + 
386                 candev->nr_sja1000_chips + 
387                 candev->nr_mcp2515_chips;
388         candev->flags &= ~CANDEV_PROGRAMMABLE_IRQ;
389
390         return 0;
391 }
392
393 /**
394  * omap2_spican_init_chip_data - Initialize chips
395  * @candev: Pointer to candevice/board structure
396  * @chipnr: Number of the CAN chip on the hardware card
397  *
398  * The function omap2_spican_init_chip_data() is used to initialize the hardware
399  * structure containing information about the CAN chips.
400  * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
401  * "sja1000".
402  * The @chip_base_addr entry represents the start of the 'official' memory map
403  * of the installed chip. It's likely that this is the same as the @io_addr
404  * argument supplied at module loading time.
405  * The @clock entry holds the chip clock value in Hz.
406  * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
407  * register. Options defined in the %sja1000.h file:
408  * %sjaCDR_CLKOUT_MASK, %sjaCDR_CLK_OFF, %sjaCDR_RXINPEN, %sjaCDR_CBP, %sjaCDR_PELICAN
409  * The entry @sja_ocr_reg holds hardware specific options for the Output Control
410  * register. Options defined in the %sja1000.h file:
411  * %sjaOCR_MODE_BIPHASE, %sjaOCR_MODE_TEST, %sjaOCR_MODE_NORMAL, %sjaOCR_MODE_CLOCK,
412  * %sjaOCR_TX0_LH, %sjaOCR_TX1_ZZ.
413  * The entry @int_clk_reg holds hardware specific options for the Clock Out
414  * register. Options defined in the %i82527.h file:
415  * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
416  * The entry @int_bus_reg holds hardware specific options for the Bus 
417  * Configuration register. Options defined in the %i82527.h file:
418  * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
419  * The entry @int_cpu_reg holds hardware specific options for the cpu interface
420  * register. Options defined in the %i82527.h file:
421  * %iCPU_CEN, %iCPU_MUX, %iCPU_SLP, %iCPU_PWD, %iCPU_DMC, %iCPU_DSC, %iCPU_RST.
422  * Return Value: The function always returns zero
423  * File: src/omap2_spican.c
424  */
425 int omap2_spican_init_chip_data(struct candevice_t *candev, int chipnr)
426 {
427         if(chipnr >= OMAP2_SPICAN_NCHIPS || chipnr < 0) {
428                 CANMSG("Error: chipnr=%d\n",chipnr);
429                 return -ENODEV;
430         }
431         
432         mcp2515_fill_chipspecops(candev->chip[chipnr]);
433 /*      candev->chip[chipnr]->chip_base_addr = 0;
434         candev->chip[chipnr]->spi_channel = 2;*/
435         candev->chip[chipnr]->chip_data = can_checked_malloc(sizeof(MCP2515_PRIV));
436         if(candev->chip[chipnr]->chip_data == NULL) return -ENOMEM;
437         memset(candev->chip[chipnr]->chip_data,0,sizeof(MCP2515_PRIV));
438
439         return 0;
440 }
441
442 int omap2_spican_register_chip_data(struct canchip_t *ch,void *data){
443         struct omap2_spican_platform_data *pdata = (struct omap2_spican_platform_data *)data;
444         ch->clock = pdata->clk;
445         ch->baudrate = pdata->baudrate;
446         int ret = 0;
447         
448         ch->flags |= CHIP_IRQ_CUSTOM;
449 //      if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ){
450 //              ch->chip_irq = pdata->irq;
451 //      }
452
453         ret = ch->chipspecops->chip_config(ch);
454         if (ret){
455                 CANMSG("Error configuring chip.\n");
456         }
457         else
458                 ch->flags |= CHIP_CONFIGURED; 
459         return ret;
460 }
461
462 /**
463  * omap2_spican_init_obj_data - Initialize message buffers
464  * @chip: Pointer to chip specific structure
465  * @objnr: Number of the message buffer
466  *
467  * The function omap2_spican_init_obj_data() is used to initialize the hardware
468  * structure containing information about the different message objects on the
469  * CAN chip. In case of the sja1000 there's only one message object but on the
470  * i82527 chip there are 15.
471  * The code below is for a i82527 chip and initializes the object base addresses
472  * The entry @obj_base_addr represents the first memory address of the message 
473  * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
474  * base address.
475  * Unless the hardware uses a segmented memory map, flags can be set zero.
476  * Return Value: The function always returns zero
477  * File: src/omap2_spican.c
478  */
479 int omap2_spican_init_obj_data(struct canchip_t *chip, int objnr)
480 {
481         chip->msgobj[objnr]->obj_base_addr=0;
482         chip->msgobj[objnr]->obj_flags=0;
483         
484         return 0;
485 }
486
487 /**
488  * omap2_spican_write_register - Low level write register routine
489  * @data: data to be written
490  * @address: memory address to write to
491  *
492  * The function omap2_spican_write_register() is used to write to hardware registers
493  * on the CAN chip. You should only have to edit this function if your hardware
494  * uses some specific write process.
495  * Return Value: The function does not return a value
496  * File: src/omap2_spican.c
497  */
498 void omap2_spican_write_register(unsigned data, can_ioptr_t address)
499 {
500         panic("omap2_spican_write_register");
501 }
502
503 /**
504  * omap2_spican_read_register - Low level read register routine
505  * @address: memory address to read from
506  *
507  * The function omap2_spican_read_register() is used to read from hardware registers
508  * on the CAN chip. You should only have to edit this function if your hardware
509  * uses some specific read process.
510  * Return Value: The function returns the value stored in @address
511  * File: src/omap2_spican.c
512  */
513 unsigned omap2_spican_read_register(can_ioptr_t address)
514 {
515         panic("omap2_spican_read_register");
516         return 0;
517 }
518
519 /**
520  * omap2_spican_program_irq - program interrupts
521  * @candev: Pointer to candevice/board structure
522  *
523  * The function omap2_spican_program_irq() is used for hardware that uses 
524  * programmable interrupts. If your hardware doesn't use programmable interrupts
525  * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and 
526  * leave this function unedited. Again this function is hardware specific so 
527  * there's no example code.
528  * Return value: The function returns zero on success or %-ENODEV on failure
529  * File: src/omap2_spican.c
530  */
531 int omap2_spican_program_irq(struct candevice_t *candev)
532 {
533         return 0;
534 }
535
536 /*******************************************************************/
537 int omap2_spican_spi_acquire_bus(struct candevice_t *candev, short channel, int block){
538         /* Subsystem is always ready to accept messages */
539         return 1;
540 }
541
542 /*******************************************************************/
543 void omap2_spican_spi_release_bus(struct candevice_t *candev, short channel){
544         return;
545 }
546
547 int omap2_spican_register(struct hwspecops_t *hwspecops)
548 {
549         hwspecops->request_io = omap2_spican_request_io;
550         hwspecops->release_io = omap2_spican_release_io;
551         hwspecops->reset = omap2_spican_reset;
552         hwspecops->init_hw_data = omap2_spican_init_hw_data;
553         hwspecops->init_chip_data = omap2_spican_init_chip_data;
554         hwspecops->init_obj_data = omap2_spican_init_obj_data;
555         hwspecops->write_register = omap2_spican_write_register;
556         hwspecops->read_register = omap2_spican_read_register;
557         hwspecops->program_irq = omap2_spican_program_irq;
558
559         // SPI specific functions
560         hwspecops->spi_transfer = omap2_spican_spi_transfer;
561         hwspecops->spi_async_transfer = omap2_spican_spi_async_transfer;
562         hwspecops->spi_acquire_bus = omap2_spican_spi_acquire_bus;
563         hwspecops->spi_release_bus = omap2_spican_spi_release_bus;
564
565         return 0;
566 }
567
568 /*******************************************************************/
569
570 static int omap2_spican_probe(struct spi_device *spi)
571 {
572         struct lincan_spican_platform_data      *spidata = spi->dev.platform_data;
573         struct omap2_spican_platform_data *pdata;
574         struct candevice_t *dev;
575         int allocated = 0;
576         
577         DEBUGMSG("Starting probe for omap2_spican...\n");
578         
579         // Structure checks and initialization
580         pdata = (struct omap2_spican_platform_data *)can_checked_malloc(sizeof(struct omap2_spican_platform_data));
581         if (pdata)
582                 memset(pdata,0,sizeof(struct omap2_spican_platform_data));
583         else
584                 return -ENOMEM;
585         
586         if (spidata)
587                 memcpy(pdata,spidata,sizeof(struct lincan_spican_platform_data));
588         else{
589                 if (!pdata->cs_change) pdata->cs_change = OMAP2_SPICAN_CS_CHANGE;
590                 if (!pdata->delay_usecs) pdata->delay_usecs = OMAP2_SPICAN_DELAY_USECS;
591         }
592         if (!pdata->clk) pdata->clk = OMAP2_SPICAN_MCP_CLK;
593         if (!pdata->baudrate) pdata->baudrate = OMAP2_SPICAN_BAUDRATE;
594         if (!pdata->speed_hz) pdata->speed_hz = OMAP2_SPICAN_SPEED_HZ;
595         if (!pdata->chiptype) pdata->chiptype = omap2_spican_defaulttype;
596
597         spin_lock_init(&pdata->spi_lock);
598         pdata->spi = spi;
599         pdata->trigger = 0;
600
601  #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
602         INIT_WORK(&pdata->lo_async_workqueue, 
603                   lo_async_workqueue_handler, 
604                   &pdata->lo_async_workqueue);
605  #else
606         INIT_WORK(&pdata->lo_async_workqueue, 
607                   lo_async_workqueue_handler);
608  #endif
609         tasklet_init(&pdata->hi_async_tasklet,
610                      hi_async_tasklet_handler, 
611                      (unsigned long)pdata);
612         
613         if (spi->irq) {
614                 DEBUGMSG("Interrupt line number %d provided.\n",spi->irq);
615                 pdata->trigger = OMAP2_SPICAN_TRIG_IRQ;
616                 pdata->irq = spi->irq;
617         }
618         else
619                 DEBUGMSG("no IRQ given, trying to find timers. Performance loss will be observed.\n");
620
621         /* Register device data in LinCAN - 1 chip, 2 msgobjs */
622         dev = register_hotplug_dev("omap2_spican",omap2_spican_register_chip_data,pdata);
623         if (!dev)
624                 goto release;
625
626         if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ) {
627                 int status = 0;
628                 DEBUGMSG("Requesting interrupt line %d.\n",spi->irq);
629                 status = set_irq_type(pdata->irq,IRQ_TYPE_EDGE_FALLING);
630                 if(status){
631                         CANMSG("Setting falling edge trigger on irq %d failed.\n", spi->irq);
632                         goto release;
633                 }
634                 status = request_irq(pdata->irq, omap2_spican_irq_handler, IRQF_DISABLED , "omap2_spican", dev);
635                 if(status){
636                         CANMSG("request_irq failed on irq %d\n", spi->irq);
637                         goto release;
638                 }
639         }
640 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
641 //      if (pdata->trigger == 0){
642         {
643                 struct clk *gt_fclk;
644                 uint32_t gt_rate;
645                 int status = 0;
646                 int prescaler = 0;
647
648                 DEBUGMSG("Setting up OMAP GPT\n");
649                 // Get the timer
650                 pdata->timer_ptr = omap_dm_timer_request();
651                 if(pdata->timer_ptr == NULL){
652                         CANMSG("No more gp timers available, bailing out\n");
653                         goto release;
654                 }
655                 
656                 // Initialize timer
657                 omap_dm_timer_set_source(pdata->timer_ptr, OMAP_TIMER_SRC_SYS_CLK); // We use the system clock 38.4 MHz
658                 
659                 omap_dm_timer_set_prescaler(pdata->timer_ptr, prescaler);               // Set prescaler to 2^(n+1)
660  
661                 // get clock rate in Hz
662                 gt_fclk = omap_dm_timer_get_fclk(pdata->timer_ptr);
663                 gt_rate = clk_get_rate(gt_fclk)/(1<<(prescaler+1));
664          
665                 // set preload, and autoreload
666                 // we set it to the clock rate in order to get 1 overflow every 1 msec
667                 omap_dm_timer_set_load(pdata->timer_ptr, 1, 0xFFFFFFFF - (uint32_t)(gt_rate / 1000));
668
669                 // Request for the irq
670                 pdata->timer_irq = omap_dm_timer_get_irq(pdata->timer_ptr);
671                 DEBUGMSG("Requesting irq %d for OMAP GPT\n", pdata->timer_irq);
672                 status = request_irq(pdata->timer_irq, omap2_spican_irq_handler, IRQF_DISABLED | IRQF_TIMER , "omap2_spican", dev);
673                 if(status){
674                         CANMSG("request_irq failed (on irq %d), bailing out\n", pdata->timer_irq);
675                   omap_dm_timer_free(pdata->timer_ptr);
676                         goto release;
677                 }
678
679                 // setup timer to trigger our IRQ on the overflow event
680                 omap_dm_timer_set_int_enable(pdata->timer_ptr, OMAP_TIMER_INT_OVERFLOW);
681 //              pdata->trigger = OMAP2_SPICAN_TRIG_GPT;
682         }
683 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
684
685         spi_set_drvdata(spi, dev);
686
687 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
688 //                      if (pdata->trigger == OMAP2_SPICAN_TRIG_GPT){
689         {
690                 // Everything's ready, let's roll!
691                 DEBUGMSG("Starting OMAP GPT\n");
692                 omap_dm_timer_start(pdata->timer_ptr);
693         }
694 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
695         DEBUGMSG("Device omap2_spican successfully configured. Have fun!\n");
696         return 0;
697         
698 release:
699         can_checked_free(pdata);
700         return -ENODEV;
701 }
702
703 static int omap2_spican_remove(struct spi_device *spi)
704 {
705         struct candevice_t *candev = spi_get_drvdata(spi);
706         struct omap2_spican_platform_data *pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
707
708         if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ){
709                 // release the IRQ handler
710                 free_irq(pdata->irq, candev);
711         }
712 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
713 //      if (pdata->trigger == OMAP2_SPICAN_TRIG_GPT){
714         {
715                 DEBUGMSG("Stopping OMAP GPT\n");
716                 omap_dm_timer_stop(pdata->timer_ptr);
717                 // release the IRQ handler
718                 free_irq(pdata->timer_irq, candev);
719           // release the timer
720           omap_dm_timer_free(pdata->timer_ptr);
721         }
722 #endif
723
724         DEBUGMSG("Removing omap2_spican from device structure...");
725         //      make sure ops on existing fds can abort cleanly
726         deregister_hotplug_dev(candev);
727         cleanup_hotplug_dev(candev);
728
729         spin_lock_irq(&pdata->spi_lock);
730         pdata->spi = NULL;
731         spi_set_drvdata(spi, NULL);
732 //      candev->sysdevptr.anydev = NULL;
733         spin_unlock_irq(&pdata->spi_lock);
734
735         DEBUGMSG("Kill tasklets.\n");
736         tasklet_kill(&pdata->hi_async_tasklet);
737
738         can_checked_free(pdata);
739         DEBUGMSG(" done.\n");
740
741         return 0;
742 }
743
744 static struct spi_driver omap2_spican_driver = {
745         .driver = {
746                 .name   = "omap2_spican",
747                 .owner  = THIS_MODULE,
748         },
749         .probe          = omap2_spican_probe,
750         .remove         = omap2_spican_remove,
751 /*      .suspend        = omap2_spican_suspend,
752         .resume         = omap2_spican_resume,*/
753 };
754
755 int omap2_spican_init(void){
756         omap2_spican_wq = create_singlethread_workqueue("omap2_spican");
757         if (omap2_spican_wq == NULL)
758                 return -1;
759         return spi_register_driver(&omap2_spican_driver);
760 }
761
762 void omap2_spican_exit(void){
763         spi_unregister_driver(&omap2_spican_driver);
764         destroy_workqueue(omap2_spican_wq);
765 }
766
767 #ifdef MODULE_ALIAS
768 MODULE_ALIAS("spi:omap2_spican");
769 #endif