1 /****************************************************************
3 Siano Mobile Silicon, Inc.
4 MDTV receiver kernel modules.
5 Copyright (C) 2006-2008, Uri Shkolnik
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ****************************************************************/
24 \brief spi bus driver module
26 This file contains implementation of the spi bus driver.
29 #include <linux/init.h>
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/moduleparam.h>
33 #include <linux/device.h>
34 #include <linux/dma-mapping.h>
35 #include <linux/platform_device.h>
36 #include <linux/delay.h>
37 #include <mach/gpio.h>
38 #include "smscoreapi.h"
39 #include "smsdbg_prn.h"
40 #include "smsspicommon.h"
41 #include "smsspiphy.h"
42 #include <linux/spi/spi.h>
44 #include <linux/kthread.h>//hzb@20100902
47 #define ANDROID_2_6_25
49 #include <linux/workqueue.h>
52 #define DRV_NAME "siano1186"
55 #define SMS_INTR_PIN 19 /* 0 for nova sip, 26 for vega in the default, 19 in the reality */
56 #define TX_BUFFER_SIZE 0x200
58 #define RX_BUFFER_SIZE (0x1000 + SPI_PACKET_SIZE + 0x100)
59 #define NUM_RX_BUFFERS 64 // change to 128
61 #define RX_BUFFER_SIZE (0x10000 + SPI_PACKET_SIZE + 0x100)
62 #define NUM_RX_BUFFERS 4 // change to 128
66 u32 g_Sms_Int_Counter=0;
67 u32 g_Sms_MsgFound_Counter=0;
69 extern unsigned long u_irq_count;
71 struct _spi_device_st {
75 struct completion write_operation;
76 struct list_head tx_queue;
80 dma_addr_t rxbuf_phy_addr;
82 struct smscore_device_t *coredev;
83 struct list_head txqueue;
85 dma_addr_t txbuf_phy_addr;
88 struct _smsspi_txmsg {
89 struct list_head node; /*! internal management */
94 struct completion completion;
95 void (*prewrite) (void *);
96 void (*postwrite) (void *);
99 struct _spi_device_st *spi_dev;
101 static int spi_resume_fail = 0 ;
102 static int spi_suspended = 0 ;
106 static void spi_worker_thread(void *arg);
109 int g_IsTokenOwned=false;
110 int g_IsTokenEnable=false;
111 struct semaphore HalfDuplexSemaphore;
112 struct task_struct *SPI_Thread;
113 static int SPI_Thread_IsStop=0;
114 #define MSG_HDR_FLAG_STATIC_MSG 0x0001 // Message is dynamic when this bit is '0'
116 static DECLARE_WORK(spi_work_queue, (void *)spi_worker_thread);
119 static u8 smsspi_preamble[] = { 0xa5, 0x5a, 0xe7, 0x7e };
121 // to support dma 16byte burst size
122 static u8 smsspi_startup[] = { 0,0,0,0,0,0,0,0,0, 0, 0xde, 0xc1, 0xa5, 0x51, 0xf1, 0xed };
124 //static u32 default_type = SMS_NOVA_A0;
125 static u32 default_type = SMS_VEGA;
126 static u32 intr_pin = SMS_INTR_PIN;
128 module_param(default_type, int, 0644);
129 MODULE_PARM_DESC(default_type, "default board type.");
131 module_param(intr_pin, int, 0644);
132 MODULE_PARM_DESC(intr_pin, "interrupt pin number.");
134 /******************************************/
136 void spilog_panic_print(void)
140 printk("spidev rxbuf_phy_addr =[0x%x]\n",spi_dev->rxbuf_phy_addr) ;
141 printk("spidev txbufphy_addr =[0x%x]\n",spi_dev->txbuf_phy_addr) ;
142 printk("spidev TX_BUFFER_SIZE = [0x%x]\n",TX_BUFFER_SIZE) ;
146 static void spi_worker_thread(void *arg)
148 struct _spi_device_st *spi_device = spi_dev;
149 struct _smsspi_txmsg *msg = NULL;
150 struct _spi_msg txmsg;
155 static u8 s_SpiTokenMsgBuf[256] = {0};
156 const u8 g_PreambleBytes[4] = { 0xa5, 0x5a, 0xe7, 0x7e};
157 struct SmsMsgHdr_ST s_SpiTokenSendMsg = {MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE, 0, 11, sizeof(struct SmsMsgHdr_ST), MSG_HDR_FLAG_STATIC_MSG};
159 memcpy( s_SpiTokenMsgBuf, g_PreambleBytes, sizeof(g_PreambleBytes) );
160 memcpy( &s_SpiTokenMsgBuf[sizeof(g_PreambleBytes)], &s_SpiTokenSendMsg, sizeof(s_SpiTokenSendMsg) );
162 PDEBUG("worker start\n");
166 if (g_IsTokenEnable){
168 if (!msg && !list_empty(&spi_device->txqueue))
169 msg = (struct _smsspi_txmsg *)list_entry(spi_device->txqueue.next, struct _smsspi_txmsg, node);
172 // TX queue empty - give up token
173 sms_debug("TX queue empty - give up token\n");
174 g_IsTokenOwned = false;
176 txmsg.buf = s_SpiTokenMsgBuf;
177 txmsg.buf_phy_addr = 0;//zzf spi_device->txbuf_phy_addr;
178 smsspi_common_transfer_msg(&spi_device->dev,&txmsg, 0);
180 sms_debug("msg is not null\n");
181 if (msg->add_preamble) {// need to add preamble
182 txmsg.len = min(msg->size + sizeof(smsspi_preamble),(size_t) TX_BUFFER_SIZE);
183 txmsg.buf = spi_device->txbuf;
184 txmsg.buf_phy_addr = spi_device->txbuf_phy_addr;
185 memcpy(txmsg.buf, smsspi_preamble, sizeof(smsspi_preamble));
186 memcpy(&txmsg.buf[sizeof(smsspi_preamble)],msg->buffer,txmsg.len - sizeof(smsspi_preamble));
187 msg->add_preamble = 0;
188 msg->buffer = (char*)msg->buffer + txmsg.len - sizeof(smsspi_preamble);
189 msg->size -= txmsg.len - sizeof(smsspi_preamble);
190 /* zero out the rest of aligned buffer */
191 memset(&txmsg.buf[txmsg.len], 0, TX_BUFFER_SIZE - txmsg.len);
192 if(spi_resume_fail||spi_suspended)
194 sms_err(KERN_EMERG " SMS1180: spi failed\n");
196 smsspi_common_transfer_msg(&spi_device->dev, &txmsg, 1);
198 } else {// donot need to add preamble
199 txmsg.len = min(msg->size, (size_t) TX_BUFFER_SIZE);
200 txmsg.buf = spi_device->txbuf;
201 txmsg.buf_phy_addr = spi_device->txbuf_phy_addr;
202 memcpy(txmsg.buf, msg->buffer, txmsg.len);
204 msg->buffer = (char*)msg->buffer + txmsg.len;
205 msg->size -= txmsg.len;
206 /* zero out the rest of aligned buffer */
207 memset(&txmsg.buf[txmsg.len], 0, TX_BUFFER_SIZE - txmsg.len);
208 if(spi_resume_fail||spi_suspended){
209 sms_err(KERN_EMERG " SMS1180: spi failed\n");
211 smsspi_common_transfer_msg(&spi_device->dev,&txmsg, 0);
217 if(0)//spi_resume_fail||spi_suspended)
219 sms_err(KERN_EMERG " SMS1180: spi failed\n") ;
221 sms_debug(KERN_EMERG "[SMS]spi_worker_thread token enable wait HalfDuplexSemaphore\n") ;
222 if (SPI_Thread_IsStop)
224 if (down_interruptible(&HalfDuplexSemaphore))
226 sms_debug(KERN_EMERG "[SMS]spi_worker_thread token enable get HalfDuplexSemaphore\n") ;
227 smsspi_common_transfer_msg(&spi_device->dev, NULL, 1);
231 sms_debug(KERN_EMERG "[SMS]spi_worker_thread token disable wait HalfDuplexSemaphore\n") ;
232 if (SPI_Thread_IsStop)
234 if (down_interruptible(&HalfDuplexSemaphore))
236 sms_debug(KERN_EMERG "[SMS]spi_worker_thread token disable get HalfDuplexSemaphore\n") ;
237 if (!msg && !list_empty(&spi_device->txqueue))
238 msg = (struct _smsspi_txmsg *)list_entry(spi_device->txqueue.next, struct _smsspi_txmsg, node);
240 if (msg->add_preamble) {// need to add preamble
241 txmsg.len = min(msg->size + sizeof(smsspi_preamble),(size_t) TX_BUFFER_SIZE);
242 txmsg.buf = spi_device->txbuf;
243 txmsg.buf_phy_addr = spi_device->txbuf_phy_addr;
244 memcpy(txmsg.buf, smsspi_preamble, sizeof(smsspi_preamble));
245 memcpy(&txmsg.buf[sizeof(smsspi_preamble)],msg->buffer,txmsg.len - sizeof(smsspi_preamble));
246 msg->add_preamble = 0;
247 msg->buffer = (char*)msg->buffer + txmsg.len - sizeof(smsspi_preamble);
248 msg->size -= txmsg.len - sizeof(smsspi_preamble);
249 /* zero out the rest of aligned buffer */
250 memset(&txmsg.buf[txmsg.len], 0, TX_BUFFER_SIZE - txmsg.len);
251 if(spi_resume_fail||spi_suspended)
253 sms_err(KERN_EMERG " SMS1180: spi failed\n");
255 smsspi_common_transfer_msg(&spi_device->dev, &txmsg, 1);
257 } else {// donot need to add preamble
258 txmsg.len = min(msg->size, (size_t) TX_BUFFER_SIZE);
259 txmsg.buf = spi_device->txbuf;
260 txmsg.buf_phy_addr = spi_device->txbuf_phy_addr;
261 memcpy(txmsg.buf, msg->buffer, txmsg.len);
263 msg->buffer = (char*)msg->buffer + txmsg.len;
264 msg->size -= txmsg.len;
265 /* zero out the rest of aligned buffer */
266 memset(&txmsg.buf[txmsg.len], 0, TX_BUFFER_SIZE - txmsg.len);
267 if(spi_resume_fail||spi_suspended)
269 sms_err(KERN_EMERG " SMS1180: spi failed\n");
271 smsspi_common_transfer_msg(&spi_device->dev,&txmsg, 0);
275 if(0)//spi_resume_fail||spi_suspended)
277 sms_err(KERN_EMERG " SMS1180: spi failed\n") ;
279 smsspi_common_transfer_msg(&spi_device->dev, NULL, 1);
284 /* if there was write, have we finished ? */
285 if (msg && !msg->size) {
286 /* call postwrite call back */
288 msg->postwrite(spi_device);
290 list_del(&msg->node);
291 complete(&msg->completion);
294 /* if there was read, did we read anything ? */
297 //check if we lost msg, if so, recover
298 if(g_Sms_MsgFound_Counter < g_Sms_Int_Counter){
299 // sms_err("we lost msg, probably becouse dma time out\n");
300 //for(i=0; i<16; i++)
302 //smsspi_common_transfer_msg(&spi_device->dev, NULL, 1);
304 g_Sms_MsgFound_Counter = g_Sms_Int_Counter;
308 PDEBUG("worker start\n");
311 /* do we have a msg to write ? */
312 if (!msg && !list_empty(&spi_device->txqueue))
313 msg = (struct _smsspi_txmsg *)list_entry(spi_device->txqueue.next, struct _smsspi_txmsg, node);
315 if (msg->add_preamble) {// need to add preamble
316 txmsg.len = min(msg->size + sizeof(smsspi_preamble),(size_t) TX_BUFFER_SIZE);
317 txmsg.buf = spi_device->txbuf;
318 txmsg.buf_phy_addr = spi_device->txbuf_phy_addr;
319 memcpy(txmsg.buf, smsspi_preamble, sizeof(smsspi_preamble));
320 memcpy(&txmsg.buf[sizeof(smsspi_preamble)],msg->buffer,txmsg.len - sizeof(smsspi_preamble));
321 msg->add_preamble = 0;
322 msg->buffer = (char*)msg->buffer + txmsg.len - sizeof(smsspi_preamble);
323 msg->size -= txmsg.len - sizeof(smsspi_preamble);
324 /* zero out the rest of aligned buffer */
325 memset(&txmsg.buf[txmsg.len], 0, TX_BUFFER_SIZE - txmsg.len);
326 if(spi_resume_fail||spi_suspended)
328 sms_err(KERN_EMERG " SMS1180: spi failed\n");
330 smsspi_common_transfer_msg(&spi_device->dev, &txmsg, 1);
332 } else {// donot need to add preamble
333 txmsg.len = min(msg->size, (size_t) TX_BUFFER_SIZE);
334 txmsg.buf = spi_device->txbuf;
335 txmsg.buf_phy_addr = spi_device->txbuf_phy_addr;
336 memcpy(txmsg.buf, msg->buffer, txmsg.len);
338 msg->buffer = (char*)msg->buffer + txmsg.len;
339 msg->size -= txmsg.len;
340 /* zero out the rest of aligned buffer */
341 memset(&txmsg.buf[txmsg.len], 0, TX_BUFFER_SIZE - txmsg.len);
342 if(spi_resume_fail||spi_suspended)
344 sms_err(KERN_EMERG " SMS1180: spi failed\n");
346 smsspi_common_transfer_msg(&spi_device->dev,&txmsg, 0);
350 if(spi_resume_fail||spi_suspended)
352 sms_err(KERN_EMERG " SMS1180: spi failed\n") ;
354 smsspi_common_transfer_msg(&spi_device->dev, NULL, 1);
358 /* if there was write, have we finished ? */
359 if (msg && !msg->size) {
360 /* call postwrite call back */
362 msg->postwrite(spi_device);
364 list_del(&msg->node);
365 complete(&msg->completion);
368 /* if there was read, did we read anything ? */
371 //check if we lost msg, if so, recover
372 if(g_Sms_MsgFound_Counter < g_Sms_Int_Counter)
374 sms_err("we lost msg, probably becouse dma time out\n");
375 //for(i=0; i<16; i++)
377 //smsspi_common_transfer_msg(&spi_device->dev, NULL, 1);
379 g_Sms_MsgFound_Counter = g_Sms_Int_Counter;
381 } while (!list_empty(&spi_device->txqueue) || msg);
385 unsigned long u_msgres_count =0;
386 static void msg_found(void *context, void *buf, int offset, int len)
388 struct _spi_device_st *spi_device = (struct _spi_device_st *) context;
389 struct smscore_buffer_t *cb =
390 (struct smscore_buffer_t
391 *)(container_of(buf, struct smscore_buffer_t, p));
393 g_Sms_MsgFound_Counter++;
396 sms_debug("Msg_found count = %d\n", u_msgres_count);
397 //printk("Msg_found count = %d\n", u_msgres_count);
399 if(len > RX_BUFFER_SIZE || offset >RX_BUFFER_SIZE )
401 sms_debug("SMS1180: msg rx over,len=0x%x,offset=0x%x\n",len,offset ) ;
402 sms_debug("SMS1180: cb->p = [0x%x]\n",(unsigned int) cb->p) ;
403 sms_debug("SMS1180: cb->phys=[0x%x]\n",(unsigned int) cb->phys) ;
409 smscore_onresponse(spi_device->coredev, cb);
414 static void smsspi_int_handler(void *context)
418 if(spi_resume_fail||spi_suspended)
420 sms_err(KERN_EMERG " SMS1180: spi failed\n") ;
424 up(&HalfDuplexSemaphore);
425 sms_debug(KERN_EMERG "[SMS]smsspi_int_handler send HalfDuplexSemaphore@intr\n") ;
427 schedule_work(&spi_work_queue);
433 static int smsspi_queue_message_and_wait(struct _spi_device_st *spi_device,
434 struct _smsspi_txmsg *msg)
436 init_completion(&msg->completion);
437 list_add_tail(&msg->node, &spi_device->txqueue);
439 if(!g_IsTokenEnable){
440 sms_debug(KERN_EMERG "[SMS]smsspi_queue_message_and_wait token disable send HalfDuplexSemaphore@writemsg\n") ;
441 up(&HalfDuplexSemaphore);
443 sms_debug(KERN_EMERG "[SMS]smsspi_queue_message_and_wait send HalfDuplexSemaphore\n") ;
446 schedule_work(&spi_work_queue);
448 wait_for_completion(&msg->completion);
453 static int smsspi_SetIntLine(void *context)
456 struct SmsMsgHdr_ST hdr;
460 MSG_SMS_SPI_INT_LINE_SET_REQ, 0, HIF_TASK,
461 sizeof(struct _Msg), 0}, {
464 struct _smsspi_txmsg msg;
466 PDEBUG("Sending SPI Set Interrupt command sequence\n");
469 msg.size = sizeof(Msg);
470 msg.alignment = SPI_PACKET_SIZE;
471 msg.add_preamble = 1;
473 msg.postwrite = NULL; /* smsspiphy_restore_clock; */
474 smsspi_queue_message_and_wait(context, &msg);
479 static int smsspi_preload(void *context)
481 struct _smsspi_txmsg msg;
482 struct _spi_device_st *spi_device = (struct _spi_device_st *) context;
485 prepareForFWDnl(spi_device->phy_dev);
486 PDEBUG("Sending SPI init sequence\n");
489 msg.buffer = smsspi_startup;
490 msg.size = sizeof(smsspi_startup);
492 msg.add_preamble = 0;
493 msg.prewrite = NULL; /* smsspiphy_reduce_clock; */
494 msg.postwrite = NULL;
496 printk(KERN_EMERG "smsmdtv: call smsspi_queue_message_and_wait\n") ;
497 smsspi_queue_message_and_wait(context, &msg);
499 ret = smsspi_SetIntLine(context);
500 sms_info("smsspi_preload set int line ret = 0x%x",ret);
507 static int smsspi_postload(void *context)
510 struct SmsMsgHdr_ST hdr;
514 MSG_SMS_SET_PERIODIC_STATS_REQ, 0, HIF_TASK,
515 sizeof(struct _Msg), 0}, {
518 struct _spi_device_st *spi_device = (struct _spi_device_st *) context;
519 struct _smsspi_txmsg msg;
521 sms_debug("Sending Period Statistics Req\n");
523 //This function just speed up the SPI clock
524 fwDnlComplete(spi_device->phy_dev, 0);
526 msg.size = sizeof(Msg);
527 msg.alignment = SPI_PACKET_SIZE;
528 msg.add_preamble = 1;
530 msg.postwrite = NULL; /* smsspiphy_restore_clock; */
541 static int smsspi_write(void *context, void *txbuf, size_t len)
543 struct _smsspi_txmsg msg;
548 msg.postwrite = NULL;
551 /* The FW is the only long message. Do not add preamble,
552 and do not padd it */
554 msg.add_preamble = 0;
555 msg.prewrite = smschipreset;
557 msg.alignment = SPI_PACKET_SIZE;
558 msg.add_preamble = 1;
561 return smsspi_queue_message_and_wait(context, &msg);
564 struct _rx_buffer_st *allocate_rx_buf(void *context, int size)
566 struct smscore_buffer_t *buf;
567 struct _spi_device_st *spi_device = (struct _spi_device_st *) context;
568 if (size > RX_BUFFER_SIZE) {
569 PERROR("Requested size is bigger than max buffer size.\n");
572 buf = smscore_getbuffer(spi_device->coredev);
573 // printk("smsmdtv: Recieved Rx buf %p physical 0x%x (contained in %p)\n", buf->p,
576 /* note: this is not mistake! the rx_buffer_st is identical to part of
577 smscore_buffer_t and we return the address of the start of the
580 // smscore_getbuffer return null, lets also return null
586 return (struct _rx_buffer_st *) &buf->p;
589 static void free_rx_buf(void *context, struct _rx_buffer_st *buf)
591 struct _spi_device_st *spi_device = (struct _spi_device_st *) context;
592 struct smscore_buffer_t *cb =
593 (struct smscore_buffer_t
594 *)(container_of(((void *)buf), struct smscore_buffer_t, p));
595 // printk("smsmdtv: buffer %p is released.\n", cb);
596 smscore_putbuffer(spi_device->coredev, cb);
599 /*! Release device STUB
601 \param[in] dev: device control block
604 static void smsspi_release(struct device *dev)
606 PDEBUG("nothing to do\n");
607 /* Nothing to release */
610 static int smsspi_driver_probe(struct platform_device *pdev)
612 PDEBUG("smsspi_probe\n") ;
616 extern void smschar_reset_device(void) ;
617 extern void smschar_set_suspend(int suspend_on);
619 extern int sms_suspend_count ;
621 #if 0 //hzb rockchip@20100525
622 static struct platform_device smsspi_device = {
626 .release = smsspi_release,
631 static struct platform_driver smsspi_driver = {
632 .probe = smsspi_driver_probe,
639 void smsspi_poweron(void)
642 ret = smsspibus_ssp_resume(spi_dev->phy_dev) ;
645 sms_err(KERN_INFO "smsspibus_ssp_resume failed\n") ;
651 void smsspi_off(void)
653 smschar_reset_device() ;
655 smsspibus_ssp_suspend(spi_dev->phy_dev) ;
659 static int siano1186_probe( struct spi_device *Smsdevice)
661 struct smsdevice_params_t params;
663 struct _spi_device_st *spi_device;
664 struct _spi_dev_cb_st common_cb;
666 sms_debug(KERN_INFO "siano1186_probe\n") ;
669 kmalloc(sizeof(struct _spi_device_st), GFP_KERNEL);
672 sms_err("spi_device is null smsspi_register\n") ;
675 spi_dev = spi_device;
677 INIT_LIST_HEAD(&spi_device->txqueue);
679 spi_device->txbuf = dma_alloc_coherent(NULL, max(TX_BUFFER_SIZE,PAGE_SIZE),&spi_device->txbuf_phy_addr, GFP_KERNEL | GFP_DMA);
681 if (!spi_device->txbuf) {
682 sms_err(KERN_INFO "%s dma_alloc_coherent(...) failed\n", __func__);
687 sms_debug(KERN_INFO "smsmdtv: spi_device->txbuf = 0x%x spi_device->txbuf_phy_addr= 0x%x\n",
688 (unsigned int)spi_device->txbuf, spi_device->txbuf_phy_addr);
690 spi_device->phy_dev = smsspiphy_init(Smsdevice, smsspi_int_handler, spi_device);
692 if (spi_device->phy_dev == 0) {
693 sms_err(KERN_INFO "%s smsspiphy_init(...) failed\n", __func__);
697 common_cb.allocate_rx_buf = allocate_rx_buf;
698 common_cb.free_rx_buf = free_rx_buf;
699 common_cb.msg_found_cb = msg_found;
700 common_cb.transfer_data_cb = smsspibus_xfer;
702 ret = smsspicommon_init(&spi_device->dev, spi_device, spi_device->phy_dev, &common_cb);
704 sms_err(KERN_INFO "%s smsspiphy_init(...) failed\n", __func__);
708 /* register in smscore */
709 memset(¶ms, 0, sizeof(params));
710 params.context = spi_device;
711 params.device = &Smsdevice->dev;
712 params.buffer_size = RX_BUFFER_SIZE;
713 params.num_buffers = NUM_RX_BUFFERS;
714 params.flags = SMS_DEVICE_NOT_READY;
715 params.sendrequest_handler = smsspi_write;
716 strcpy(params.devpath, "spi");
717 params.device_type = default_type;
721 /* params.setmode_handler = smsspi_setmode; */
724 SMS_DEVICE_FAMILY2 | SMS_DEVICE_NOT_READY |
726 params.preload_handler = smsspi_preload;
727 params.postload_handler = smsspi_postload;
731 g_IsTokenOwned = false;
732 init_MUTEX_LOCKED(&HalfDuplexSemaphore);
733 SPI_Thread = kthread_run(spi_worker_thread,NULL,"cmmb_spi_thread");
734 SPI_Thread_IsStop = 0;
738 ret = smscore_register_device(¶ms, &spi_device->coredev);
740 sms_err(KERN_INFO "%s smscore_register_device(...) failed\n", __func__);
741 goto reg_device_error;
744 ret = smscore_start_device(spi_device->coredev);
746 sms_err(KERN_INFO "%s smscore_start_device(...) failed\n", __func__);
747 goto start_device_error;
749 spi_resume_fail = 0 ;
752 sms_info(KERN_INFO "siano1186_probe exiting\n") ;
758 smscore_unregister_device(spi_device->coredev);
763 smsspiphy_deinit(spi_device->phy_dev);
767 #if 0 //spi buff kmalloc
768 kfree(spi_device->txbuf);
770 dma_free_coherent(NULL, TX_BUFFER_SIZE, spi_device->txbuf,spi_device->txbuf_phy_addr);
775 sms_err("exiting error %d\n", ret);
781 void smsspi_remove(void)
783 struct _spi_device_st *spi_device = spi_dev;
784 sms_info(KERN_INFO "smsmdtv: in smsspi_unregister\n") ;
787 SPI_Thread_IsStop = 1;
788 up(&HalfDuplexSemaphore);
789 sms_info("stop kthread \n");
790 ret = kthread_stop(SPI_Thread);
791 sms_info("stop kthread ret = 0x%x\n",ret);
793 /* stop interrupts */
794 smsspiphy_deinit(spi_device->phy_dev);
796 smscore_unregister_device(spi_device->coredev);
798 dma_free_coherent(NULL, TX_BUFFER_SIZE, spi_device->txbuf,spi_device->txbuf_phy_addr);
802 sms_info("smsspi_remove exiting\n");
805 static struct spi_driver siano1186_driver = {
808 .bus = &spi_bus_type,
809 .owner = THIS_MODULE,
811 .probe = siano1186_probe,
812 .remove = __devexit_p(smsspi_remove),
815 int smsspi_register(void)
817 sms_info(KERN_INFO "smsmdtv: in smsspi_register\n") ;
818 spi_register_driver(&siano1186_driver);
821 void smsspi_unregister(void)
823 spi_unregister_driver(&siano1186_driver);