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
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>
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"
27 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
29 #include <asm/uaccess.h>
30 #include <plat/dmtimer.h>
31 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
33 static const char* omap2_spican_defaulttype = "mcp2515";
35 static struct workqueue_struct *omap2_spican_wq;
37 /*******************************************************************/
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.
42 static void omap2_spican_spi_complete(void *arg)
44 DEBUGMSG("SPICAN sync: complete\n");
48 ssize_t omap2_spican_spi_sync(struct candevice_t *candev, struct spi_message *message)
50 DECLARE_COMPLETION_ONSTACK(done);
51 struct omap2_spican_platform_data *pdata;
57 panic("SPICAN: trying to send null pointered message");
59 pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
63 message->complete = omap2_spican_spi_complete;
64 message->context = &done;
65 spin_lock_irq(&pdata->spi_lock);
66 if (pdata->spi == NULL)
69 DEBUGMSG("SPICAN sync: transfer\n");
70 status = spi_async(pdata->spi, message);
72 spin_unlock_irq(&pdata->spi_lock);
75 while (!wait_for_completion_interruptible_timeout(&done, msecs_to_jiffies(10))) {
76 DEBUGMSG("SPICAN sync: timeout 10 msecs\n");
78 // do { ;} while (wait_for_completion_interruptible(&done));
79 status = message->status;
81 status = message->actual_length;
86 static ssize_t omap2_spican_spi_transfer(struct candevice_t *candev,void *tx, void *rx, uint16_t len)
88 struct omap2_spican_platform_data *pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
89 struct spi_transfer t = {
94 .speed_hz = pdata->speed_hz,
102 if(len > SPI_BUF_LEN) panic("long CAN spi transfer: %u",len);
104 spi_message_init(&m);
106 spi_message_add_tail(&t, &m);
107 status = omap2_spican_spi_sync(candev, &m);
111 static void hi_async_tasklet_handler(unsigned long data)
113 struct omap2_spican_platform_data *pdata=(struct omap2_spican_platform_data *)data;
121 n = find_first_bit(pdata->hi_async_done_map,OMAP2_SPICAN_PRE_ASYNC);
122 if (n == OMAP2_SPICAN_PRE_ASYNC)
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);
129 clear_bit(n,pdata->hi_async_done_map);
130 clear_bit(n,pdata->async_req_map);
131 } while (n < OMAP2_SPICAN_PRE_ASYNC);
134 static void lo_async_workqueue_handler(struct work_struct *work)
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;
144 n = find_first_bit(pdata->lo_async_done_map,OMAP2_SPICAN_PRE_ASYNC);
145 if (n >= OMAP2_SPICAN_PRE_ASYNC)
148 DEBUGMSG("SPICAN async %d: low priority workqueue\n",n);
149 async = pdata->async + n;
152 async->complete(async->data,async->count);
154 clear_bit(n,pdata->lo_async_done_map);
155 clear_bit(n,pdata->async_req_map);
156 } while (n < OMAP2_SPICAN_PRE_ASYNC);
159 static void omap2_spican_spi_async_complete(void *arg)
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]);
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);*/
174 as->complete(as->data,as->count);
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");
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);
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)
189 struct omap2_spican_platform_data *pdata;
190 struct omap2_spican_async_t *async;
197 pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
201 if (count > OMAP2_SPICAN_MAX_TRANSFERS)
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)
209 } while (test_and_set_bit(n,pdata->async_req_map));
211 async = pdata->async+n;
213 memset(async,0,sizeof(struct omap2_spican_async_t));
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);
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;
226 spi_message_init(&async->m);
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");
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;
239 spi_message_add_tail(&async->t[i], &async->m);
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)
248 DEBUGMSG("SPICAN async %d: transfer\n",n);
249 status = spi_async(pdata->spi, &async->m);
251 spin_unlock_irq(&pdata->spi_lock);
254 clear_bit(n,pdata->async_req_map);
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
266 * Return Value: Interrupt handled status is returned
267 * File: src/omap2_spican.c
269 static irqreturn_t omap2_spican_irq_handler(int irq, void *dev_id)
271 struct candevice_t *candev = dev_id;
272 struct omap2_spican_platform_data *pdata;
279 pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
283 /* if (((pdata->trigger == OMAP2_SPICAN_TRIG_GPT) && (irq != pdata->timer_irq))
284 || ((pdata->trigger == OMAP2_SPICAN_TRIG_IRQ) && (irq != pdata->irq))
287 if ((irq != pdata->timer_irq) && (irq != pdata->irq))
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
298 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
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]);
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
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
323 int omap2_spican_request_io(struct candevice_t *candev)
329 * omap2_spican_release_io - free reserved io memory range
330 * @candev: pointer to candevice/board which releases io
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
340 int omap2_spican_release_io(struct candevice_t *candev)
346 * omap2_spican_reset - hardware reset routine
347 * @candev: Pointer to candevice/board structure
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
355 int omap2_spican_reset(struct candevice_t *candev)
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]);
366 * omap2_spican_init_hw_data - Initialize hardware cards
367 * @candev: Pointer to candevice/board structure
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
379 int omap2_spican_init_hw_data(struct candevice_t *candev)
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;
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
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
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
425 int omap2_spican_init_chip_data(struct candevice_t *candev, int chipnr)
427 if(chipnr >= OMAP2_SPICAN_NCHIPS || chipnr < 0) {
428 CANMSG("Error: chipnr=%d\n",chipnr);
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));
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;
448 ch->flags |= CHIP_IRQ_CUSTOM;
449 // if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ){
450 // ch->chip_irq = pdata->irq;
453 ret = ch->chipspecops->chip_config(ch);
455 CANMSG("Error configuring chip.\n");
458 ch->flags |= CHIP_CONFIGURED;
463 * omap2_spican_init_obj_data - Initialize message buffers
464 * @chip: Pointer to chip specific structure
465 * @objnr: Number of the message buffer
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
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
479 int omap2_spican_init_obj_data(struct canchip_t *chip, int objnr)
481 chip->msgobj[objnr]->obj_base_addr=0;
482 chip->msgobj[objnr]->obj_flags=0;
488 * omap2_spican_write_register - Low level write register routine
489 * @data: data to be written
490 * @address: memory address to write to
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
498 void omap2_spican_write_register(unsigned data, can_ioptr_t address)
500 panic("omap2_spican_write_register");
504 * omap2_spican_read_register - Low level read register routine
505 * @address: memory address to read from
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
513 unsigned omap2_spican_read_register(can_ioptr_t address)
515 panic("omap2_spican_read_register");
520 * omap2_spican_program_irq - program interrupts
521 * @candev: Pointer to candevice/board structure
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
531 int omap2_spican_program_irq(struct candevice_t *candev)
536 /*******************************************************************/
537 int omap2_spican_spi_acquire_bus(struct candevice_t *candev, short channel, int block){
538 /* Subsystem is always ready to accept messages */
542 /*******************************************************************/
543 void omap2_spican_spi_release_bus(struct candevice_t *candev, short channel){
547 int omap2_spican_register(struct hwspecops_t *hwspecops)
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;
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;
568 /*******************************************************************/
570 static int omap2_spican_probe(struct spi_device *spi)
572 struct lincan_spican_platform_data *spidata = spi->dev.platform_data;
573 struct omap2_spican_platform_data *pdata;
574 struct candevice_t *dev;
577 DEBUGMSG("Starting probe for omap2_spican...\n");
579 // Structure checks and initialization
580 pdata = (struct omap2_spican_platform_data *)can_checked_malloc(sizeof(struct omap2_spican_platform_data));
582 memset(pdata,0,sizeof(struct omap2_spican_platform_data));
587 memcpy(pdata,spidata,sizeof(struct lincan_spican_platform_data));
589 if (!pdata->cs_change) pdata->cs_change = OMAP2_SPICAN_CS_CHANGE;
590 if (!pdata->delay_usecs) pdata->delay_usecs = OMAP2_SPICAN_DELAY_USECS;
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;
597 spin_lock_init(&pdata->spi_lock);
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);
606 INIT_WORK(&pdata->lo_async_workqueue,
607 lo_async_workqueue_handler);
609 tasklet_init(&pdata->hi_async_tasklet,
610 hi_async_tasklet_handler,
611 (unsigned long)pdata);
614 DEBUGMSG("Interrupt line number %d provided.\n",spi->irq);
615 pdata->trigger = OMAP2_SPICAN_TRIG_IRQ;
616 pdata->irq = spi->irq;
619 DEBUGMSG("no IRQ given, trying to find timers. Performance loss will be observed.\n");
621 /* Register device data in LinCAN - 1 chip, 2 msgobjs */
622 dev = register_hotplug_dev("omap2_spican",omap2_spican_register_chip_data,pdata);
626 if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ) {
628 DEBUGMSG("Requesting interrupt line %d.\n",spi->irq);
629 status = set_irq_type(pdata->irq,IRQ_TYPE_EDGE_FALLING);
631 CANMSG("Setting falling edge trigger on irq %d failed.\n", spi->irq);
634 status = request_irq(pdata->irq, omap2_spican_irq_handler, IRQF_DISABLED , "omap2_spican", dev);
636 CANMSG("request_irq failed on irq %d\n", spi->irq);
640 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
641 // if (pdata->trigger == 0){
648 DEBUGMSG("Setting up OMAP GPT\n");
650 pdata->timer_ptr = omap_dm_timer_request();
651 if(pdata->timer_ptr == NULL){
652 CANMSG("No more gp timers available, bailing out\n");
657 omap_dm_timer_set_source(pdata->timer_ptr, OMAP_TIMER_SRC_SYS_CLK); // We use the system clock 38.4 MHz
659 omap_dm_timer_set_prescaler(pdata->timer_ptr, prescaler); // Set prescaler to 2^(n+1)
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));
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));
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);
674 CANMSG("request_irq failed (on irq %d), bailing out\n", pdata->timer_irq);
675 omap_dm_timer_free(pdata->timer_ptr);
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;
683 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
685 spi_set_drvdata(spi, dev);
687 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
688 // if (pdata->trigger == OMAP2_SPICAN_TRIG_GPT){
690 // Everything's ready, let's roll!
691 DEBUGMSG("Starting OMAP GPT\n");
692 omap_dm_timer_start(pdata->timer_ptr);
694 #endif /* CONFIG_OC_LINCAN_OMAP_DM_TIMER */
695 DEBUGMSG("Device omap2_spican successfully configured. Have fun!\n");
699 can_checked_free(pdata);
703 static int omap2_spican_remove(struct spi_device *spi)
705 struct candevice_t *candev = spi_get_drvdata(spi);
706 struct omap2_spican_platform_data *pdata = (struct omap2_spican_platform_data *)(candev->sysdevptr.anydev);
708 if (pdata->trigger == OMAP2_SPICAN_TRIG_IRQ){
709 // release the IRQ handler
710 free_irq(pdata->irq, candev);
712 #ifdef CONFIG_OC_LINCAN_OMAP_DM_TIMER
713 // if (pdata->trigger == OMAP2_SPICAN_TRIG_GPT){
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);
720 omap_dm_timer_free(pdata->timer_ptr);
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);
729 spin_lock_irq(&pdata->spi_lock);
731 spi_set_drvdata(spi, NULL);
732 // candev->sysdevptr.anydev = NULL;
733 spin_unlock_irq(&pdata->spi_lock);
735 DEBUGMSG("Kill tasklets.\n");
736 tasklet_kill(&pdata->hi_async_tasklet);
738 can_checked_free(pdata);
739 DEBUGMSG(" done.\n");
744 static struct spi_driver omap2_spican_driver = {
746 .name = "omap2_spican",
747 .owner = THIS_MODULE,
749 .probe = omap2_spican_probe,
750 .remove = omap2_spican_remove,
751 /* .suspend = omap2_spican_suspend,
752 .resume = omap2_spican_resume,*/
755 int omap2_spican_init(void){
756 omap2_spican_wq = create_singlethread_workqueue("omap2_spican");
757 if (omap2_spican_wq == NULL)
759 return spi_register_driver(&omap2_spican_driver);
762 void omap2_spican_exit(void){
763 spi_unregister_driver(&omap2_spican_driver);
764 destroy_workqueue(omap2_spican_wq);
768 MODULE_ALIAS("spi:omap2_spican");