1 #include <linux/module.h>
\r
2 #include <linux/init.h>
\r
3 #include <linux/kernel.h>
\r
4 #include <linux/mutex.h>
\r
5 #include <linux/serial_reg.h>
\r
6 #include <linux/circ_buf.h>
\r
7 #include <linux/gfp.h>
\r
8 #include <linux/tty.h>
\r
9 #include <linux/tty_flip.h>
\r
10 #include <linux/interrupt.h>
\r
11 #include <linux/platform_device.h>
\r
12 #include <linux/spi/spi.h>
\r
13 #include <linux/delay.h>
\r
14 #include <linux/module.h>
\r
15 #include <linux/ioport.h>
\r
16 #include <linux/console.h>
\r
17 #include <linux/sysrq.h>
\r
18 #include <mach/gpio.h>
\r
19 #include <mach/iomux.h>
\r
21 #include <asm/irq.h>
\r
22 #include <linux/miscdevice.h>
\r
23 #include <linux/poll.h>
\r
24 #include <linux/sched.h>
\r
25 #include <linux/kthread.h>
\r
26 #include <linux/jiffies.h>
\r
27 #include <linux/i2c.h>
\r
28 #include <mach/rk2818_iomap.h>
\r
30 #include <mach/spi_fpga.h>
\r
32 #if defined(CONFIG_SPI_UART_DEBUG)
\r
33 #define DBG(x...) printk(x)
\r
38 #define SPI_UART_TEST 0
\r
40 #define SPI_UART_FIFO_LEN 32
\r
41 #define SPI_UART_TXRX_BUF 0 //send or recieve several bytes one time
\r
43 static struct tty_driver *spi_uart_tty_driver;
\r
44 /*------------------------ÒÔÏÂÊÇspi2uart±äÁ¿-----------------------*/
\r
46 #define UART_NR 1 /* Number of UARTs this driver can handle */
\r
48 #define UART_XMIT_SIZE PAGE_SIZE
\r
49 #define WAKEUP_CHARS 1024
\r
51 #define circ_empty(circ) ((circ)->head == (circ)->tail)
\r
52 #define circ_clear(circ) ((circ)->head = (circ)->tail = 0)
\r
54 #define circ_chars_pending(circ) \
\r
55 (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
\r
57 #define circ_chars_free(circ) \
\r
58 (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
\r
63 static struct spi_uart *spi_uart_table[UART_NR];
\r
64 static DEFINE_SPINLOCK(spi_uart_table_lock);
\r
66 #if SPI_UART_TXRX_BUF
\r
67 static int spi_uart_write_buf(struct spi_uart *uart, unsigned char *buf, int len)
\r
69 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
70 int index = port->uart.index;
\r
72 unsigned char tx_buf[SPI_UART_TXRX_BUF+2];//uart's tx fifo max lenth + 1
\r
74 reg = ((((reg) | ICE_SEL_UART) & ICE_SEL_WRITE) | ICE_SEL_UART_CH(index));
\r
75 tx_buf[0] = reg & 0xff;
\r
77 memcpy(tx_buf+2, buf, len);
\r
78 spi_write(port->spi, (const u8 *)&tx_buf, len+2);
\r
79 DBG("%s,buf=0x%x,len=0x%x\n",__FUNCTION__,reg&0xff,(int)tx_buf,len);
\r
84 static int spi_uart_read_buf(struct spi_uart *uart, unsigned char *buf, int len)
\r
86 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
87 int index = port->uart.index;
\r
88 int reg = 0,stat = 0;
\r
89 unsigned char tx_buf[1],rx_buf[SPI_UART_FIFO_LEN+1];
\r
91 reg = (((reg) | ICE_SEL_UART) | ICE_SEL_READ | ICE_SEL_UART_CH(index));
\r
92 tx_buf[0] = reg & 0xff;
\r
93 //give fpga 8 clks for reading data
\r
94 stat = spi_write_then_read(port->spi, (const u8 *)&tx_buf, 1, rx_buf, len+1);
\r
95 memcpy(buf, rx_buf+1, len);
\r
96 DBG("%s,buf=0x%x,len=0x%x\n",__FUNCTION__,reg&0xff,(int)buf,len);
\r
102 static int spi_uart_add_port(struct spi_uart *uart)
\r
104 int index, ret = -EBUSY;
\r
106 kref_init(&uart->kref);
\r
107 mutex_init(&uart->open_lock);
\r
108 spin_lock_init(&uart->write_lock);
\r
109 spin_lock_init(&uart->irq_lock);
\r
111 spin_lock(&spi_uart_table_lock);
\r
112 for (index = 0; index < UART_NR; index++)
\r
114 if (!spi_uart_table[index]) {
\r
115 uart->index = index;
\r
116 //printk("index=%d\n\n",index);
\r
117 spi_uart_table[index] = uart;
\r
122 spin_unlock(&spi_uart_table_lock);
\r
127 static struct spi_uart *spi_uart_port_get(unsigned index)
\r
129 struct spi_uart *uart;
\r
131 if (index >= UART_NR)
\r
134 spin_lock(&spi_uart_table_lock);
\r
135 uart = spi_uart_table[index];
\r
136 uart->index = index;
\r
137 printk("uart->index=%d\n",uart->index);
\r
139 kref_get(&uart->kref);
\r
140 spin_unlock(&spi_uart_table_lock);
\r
145 static void spi_uart_port_destroy(struct kref *kref)
\r
147 struct spi_uart *uart =
\r
148 container_of(kref, struct spi_uart, kref);
\r
152 static void spi_uart_port_put(struct spi_uart *uart)
\r
154 kref_put(&uart->kref, spi_uart_port_destroy);
\r
157 static void spi_uart_port_remove(struct spi_uart *uart)
\r
159 struct spi_device *spi;
\r
160 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
162 BUG_ON(spi_uart_table[uart->index] != uart);
\r
164 spin_lock(&spi_uart_table_lock);
\r
165 spi_uart_table[uart->index] = NULL;
\r
166 spin_unlock(&spi_uart_table_lock);
\r
169 * We're killing a port that potentially still is in use by
\r
170 * the tty layer. Be careful to arrange for the tty layer to
\r
171 * give up on that port ASAP.
\r
172 * Beware: the lock ordering is critical.
\r
174 mutex_lock(&uart->open_lock);
\r
175 //mutex_lock(&port->spi_lock);
\r
179 //mutex_unlock(&port->spi_lock);
\r
181 tty_hangup(uart->tty);
\r
182 mutex_unlock(&uart->open_lock);
\r
184 spi_uart_port_put(uart);
\r
187 static unsigned int spi_uart_get_mctrl(struct spi_uart *uart)
\r
189 unsigned char status;
\r
191 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
193 status = spi_in(port, UART_MSR, SEL_UART);//
\r
196 if (status & UART_MSR_DCD)
\r
198 if (status & UART_MSR_RI)
\r
200 if (status & UART_MSR_DSR)
\r
202 if (status & UART_MSR_CTS)
\r
205 if (status & UART_MSR_CTS)
\r
206 ret = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
\r
207 DBG("Enter::%s,LINE=%d,ret=0x%x************************\n",__FUNCTION__,__LINE__,ret);
\r
211 static void spi_uart_write_mctrl(struct spi_uart *uart, unsigned int mctrl)
\r
213 unsigned char mcr = 0;
\r
214 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
216 if (mctrl & TIOCM_RTS)
\r
218 mcr |= UART_MCR_RTS;
\r
219 mcr |= UART_MCR_AFE;
\r
221 //if (mctrl & TIOCM_DTR)
\r
222 // mcr |= UART_MCR_DTR;
\r
223 //if (mctrl & TIOCM_OUT1)
\r
224 // mcr |= UART_MCR_OUT1;
\r
225 //if (mctrl & TIOCM_OUT2)
\r
226 // mcr |= UART_MCR_OUT2;
\r
227 //if (mctrl & TIOCM_LOOP)
\r
228 // mcr |= UART_MCR_LOOP;
\r
232 DBG("Enter::%s,LINE=%d,mcr=0x%x\n",__FUNCTION__,__LINE__,mcr);
\r
233 spi_out(port, UART_MCR, mcr, SEL_UART);
\r
236 static inline void spi_uart_update_mctrl(struct spi_uart *uart,
\r
237 unsigned int set, unsigned int clear)
\r
240 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
242 uart->mctrl = (old & ~clear) | set;
\r
243 if (old != uart->mctrl)
\r
244 spi_uart_write_mctrl(uart, uart->mctrl);
\r
247 #define spi_uart_set_mctrl(uart, x) spi_uart_update_mctrl(uart, x, 0)
\r
248 #define spi_uart_clear_mctrl(uart, x) spi_uart_update_mctrl(uart, 0, x)
\r
250 static void spi_uart_change_speed(struct spi_uart *uart,
\r
251 struct ktermios *termios,
\r
252 struct ktermios *old)
\r
254 unsigned char cval, fcr = 0;
\r
255 unsigned int baud, quot;
\r
256 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
258 switch (termios->c_cflag & CSIZE) {
\r
260 cval = UART_LCR_WLEN5;
\r
263 cval = UART_LCR_WLEN6;
\r
266 cval = UART_LCR_WLEN7;
\r
270 cval = UART_LCR_WLEN8;
\r
274 if (termios->c_cflag & CSTOPB)
\r
275 cval |= UART_LCR_STOP;
\r
276 if (termios->c_cflag & PARENB)
\r
277 cval |= UART_LCR_PARITY;
\r
278 if (!(termios->c_cflag & PARODD))
\r
279 cval |= UART_LCR_EPAR;
\r
282 baud = tty_termios_baud_rate(termios);
\r
284 baud = 115200; /* Special case: B0 rate. */
\r
285 if (baud <= uart->uartclk)
\r
288 * Oops, the quotient was zero. Try again with the old
\r
289 * baud rate if possible, otherwise default to 115200.
\r
291 termios->c_cflag &= ~CBAUD;
\r
293 termios->c_cflag |= old->c_cflag & CBAUD;
\r
296 termios->c_cflag |= B115200;
\r
298 //quot = (2 * uart->uartclk + baud) / (2 * baud);
\r
299 quot = (uart->uartclk / baud);
\r
300 printk("baud=%d,quot=0x%x\n",baud,quot);
\r
302 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
\r
304 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
\r
306 uart->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
\r
307 if (termios->c_iflag & INPCK)
\r
308 uart->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
\r
309 if (termios->c_iflag & (BRKINT | PARMRK))
\r
310 uart->read_status_mask |= UART_LSR_BI;
\r
313 * Characters to ignore
\r
315 uart->ignore_status_mask = 0;
\r
316 if (termios->c_iflag & IGNPAR)
\r
317 uart->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
\r
318 if (termios->c_iflag & IGNBRK) {
\r
319 uart->ignore_status_mask |= UART_LSR_BI;
\r
321 * If we're ignoring parity and break indicators,
\r
322 * ignore overruns too (for real raw support).
\r
324 if (termios->c_iflag & IGNPAR)
\r
325 uart->ignore_status_mask |= UART_LSR_OE;
\r
329 * ignore all characters if CREAD is not set
\r
331 if ((termios->c_cflag & CREAD) == 0)
\r
332 uart->ignore_status_mask |= UART_LSR_DR;
\r
335 * CTS flow control flag and modem status interrupts
\r
337 uart->ier &= ~UART_IER_MSI;
\r
338 if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))
\r
340 //uart->ier |= UART_IER_MSI;
\r
341 //uart->mcr = UART_MCR_RTS;//mcr = UART_MCR_RTS while start RTSCTS
\r
346 spi_out(port, UART_IER, uart->ier, SEL_UART);
\r
347 spi_out(port, UART_LCR, cval | UART_LCR_DLAB, SEL_UART);
\r
348 spi_out(port, UART_DLL, quot & 0xff, SEL_UART);
\r
349 spi_out(port, UART_DLM, quot >> 8, SEL_UART);
\r
350 spi_out(port, UART_LCR, cval, SEL_UART);
\r
351 spi_out(port, UART_FCR, fcr, SEL_UART);
\r
352 DBG("Enter::%s,LINE=%d,baud=%d,uart->ier=0x%x,cval=0x%x,fcr=0x%x,quot=0x%x\n",
\r
353 __FUNCTION__,__LINE__,baud,uart->ier,cval,fcr,quot);
\r
354 spi_uart_write_mctrl(uart, uart->mctrl);
\r
357 static void spi_uart_start_tx(struct spi_uart *uart)
\r
359 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
361 //unsigned long flags;
\r
362 if (!(uart->ier & UART_IER_THRI)) {
\r
363 //spin_lock_irqsave(&uart->write_lock, flags);
\r
364 uart->ier |= UART_IER_THRI;
\r
365 spi_out(port, UART_IER, uart->ier, SEL_UART);
\r
366 //spin_unlock_irqrestore(&uart->write_lock, flags);
\r
370 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
374 static void spi_uart_stop_tx(struct spi_uart *uart)
\r
376 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
377 //unsigned long flags;
\r
378 if (uart->ier & UART_IER_THRI) {
\r
379 //spin_lock_irqsave(&uart->write_lock, flags);
\r
380 uart->ier &= ~UART_IER_THRI;
\r
381 spi_out(port, UART_IER, uart->ier, SEL_UART);
\r
382 //spin_unlock_irqrestore(&uart->write_lock, flags);
\r
385 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
388 static void spi_uart_stop_rx(struct spi_uart *uart)
\r
390 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
391 uart->ier &= ~UART_IER_RLSI;
\r
392 uart->read_status_mask &= ~UART_LSR_DR;
\r
393 spi_out(port, UART_IER, uart->ier, SEL_UART);
\r
396 static void spi_uart_receive_chars(struct spi_uart *uart, unsigned int *status)
\r
398 struct tty_struct *tty = uart->tty;
\r
399 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
400 unsigned int ch, flag;
\r
401 int max_count = 1024;
\r
403 #if SPI_UART_TXRX_BUF
\r
404 int ret,count,stat = 0,num = 0;
\r
405 unsigned char buf[SPI_UART_FIFO_LEN];
\r
407 while (max_count >0 )
\r
409 ret = spi_in(port, UART_RX, SEL_UART);
\r
410 count = (ret >> 8) & 0xff;
\r
413 buf[0] = ret & 0xff;
\r
416 stat = spi_uart_read_buf(uart,buf+1,count-1);
\r
418 printk("err:%s:stat=%d,fail to read uart data because of spi bus error!\n",__FUNCTION__,stat);
\r
420 max_count -= count;
\r
421 while (count-- >0 )
\r
425 tty_insert_flip_char(tty, ch, flag);
\r
428 tty_flip_buffer_push(tty);
\r
430 printk("r%d\n",1024-max_count);
\r
433 while (--max_count >0 )
\r
435 ch = spi_in(port, UART_RX, SEL_UART);//
\r
436 //printk("0x%x,",ch&0xff);
\r
440 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
\r
441 UART_LSR_FE | UART_LSR_OE))) {
\r
443 * For statistics only
\r
445 if (*status & UART_LSR_BI) {
\r
446 *status &= ~(UART_LSR_FE | UART_LSR_PE);
\r
447 uart->icount.brk++;
\r
448 } else if (*status & UART_LSR_PE)
\r
449 uart->icount.parity++;
\r
450 else if (*status & UART_LSR_FE)
\r
451 uart->icount.frame++;
\r
452 if (*status & UART_LSR_OE)
\r
453 uart->icount.overrun++;
\r
456 * Mask off conditions which should be ignored.
\r
458 *status &= uart->read_status_mask;
\r
459 if (*status & UART_LSR_BI) {
\r
461 } else if (*status & UART_LSR_PE)
\r
463 else if (*status & UART_LSR_FE)
\r
467 if ((*status & uart->ignore_status_mask & ~UART_LSR_OE) == 0)
\r
468 tty_insert_flip_char(tty, ch, flag);
\r
471 * Overrun is special. Since it's reported immediately,
\r
472 * it doesn't affect the current character.
\r
474 if (*status & ~uart->ignore_status_mask & UART_LSR_OE)
\r
475 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
\r
476 *status = spi_in(port, UART_LSR, SEL_UART);
\r
477 if(!(*status & UART_LSR_DR))
\r
481 DBG("Enter::%s,LINE=%d,rx_count=%d********\n",__FUNCTION__,__LINE__,(1024-max_count));
\r
482 printk("r%d\n",1024-max_count);
\r
483 tty_flip_buffer_push(tty);
\r
489 static void spi_uart_transmit_chars(struct spi_uart *uart)
\r
491 struct circ_buf *xmit = &uart->xmit;
\r
493 #if SPI_UART_TXRX_BUF
\r
494 unsigned char buf[SPI_UART_FIFO_LEN];
\r
496 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
498 if (uart->x_char) {
\r
499 spi_out(port, UART_TX, uart->x_char, SEL_UART);
\r
502 printk("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
505 if (circ_empty(xmit) || uart->tty->stopped || uart->tty->hw_stopped) {
\r
506 spi_uart_stop_tx(uart);
\r
507 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
508 //printk("circ_empty()\n");
\r
513 #if SPI_UART_TXRX_BUF
\r
514 //send several bytes one time
\r
516 while(count < SPI_UART_FIFO_LEN)
\r
518 buf[count] = xmit->buf[xmit->tail];
\r
519 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
\r
522 if (circ_empty(xmit))
\r
525 spi_uart_write_buf(uart,buf,count);
\r
527 //send one byte one time
\r
528 count = SPI_UART_FIFO_LEN;//
\r
531 spi_out(port, UART_TX, xmit->buf[xmit->tail], SEL_UART);
\r
532 //printk("0x%x,",xmit->buf[xmit->tail]);
\r
533 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
\r
536 if (circ_empty(xmit))
\r
541 DBG("Enter::%s,LINE=%d,tx_count=%d\n",__FUNCTION__,__LINE__,(32-count));
\r
542 if (circ_chars_pending(xmit) < WAKEUP_CHARS)
\r
544 tty_wakeup(uart->tty);
\r
547 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
548 if (circ_empty(xmit))
\r
550 DBG("circ_empty(xmit)\n");
\r
551 spi_uart_stop_tx(uart);
\r
555 printk("t%d\n",32-count);
\r
557 DBG("uart->tty->hw_stopped = %d\n",uart->tty->hw_stopped);
\r
561 static void spi_uart_check_modem_status(struct spi_uart *uart)
\r
564 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
566 status = spi_in(port, UART_MSR, SEL_UART);//
\r
567 DBG("Enter::%s,LINE=%d,status=0x%x*******\n",__FUNCTION__,__LINE__,status);
\r
568 if ((status & UART_MSR_ANY_DELTA) == 0)
\r
571 if (status & UART_MSR_TERI)
\r
572 uart->icount.rng++;
\r
573 if (status & UART_MSR_DDSR)
\r
574 uart->icount.dsr++;
\r
575 if (status & UART_MSR_DDCD)
\r
576 uart->icount.dcd++;
\r
577 if (status & UART_MSR_DCTS) {
\r
578 uart->icount.cts++;
\r
579 if (uart->tty->termios->c_cflag & CRTSCTS) {
\r
580 int cts = (status & UART_MSR_CTS);
\r
581 if (uart->tty->hw_stopped) {
\r
583 uart->tty->hw_stopped = 0;
\r
584 spi_uart_start_tx(uart);
\r
585 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
586 tty_wakeup(uart->tty);
\r
590 uart->tty->hw_stopped = 1;
\r
591 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
592 spi_uart_stop_tx(uart);
\r
597 DBG("Enter::%s,LINE=%d,status=0x%x*******\n",__FUNCTION__,__LINE__,status);
\r
603 #define UART_TEST_LEN 16 //8bit
\r
604 unsigned char buf_test_uart[UART_TEST_LEN];
\r
606 void spi_uart_test_init(struct spi_fpga_port *port)
\r
608 unsigned char cval, fcr = 0;
\r
609 unsigned int baud, quot;
\r
610 unsigned char mcr = 0;
\r
613 DBG("Enter::%s,LINE=%d,mcr=0x%x\n",__FUNCTION__,__LINE__,mcr);
\r
614 spi_out(port, UART_MCR, mcr, SEL_UART);
\r
616 cval = UART_LCR_WLEN8;
\r
617 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
\r
618 quot = 6000000 / baud;
\r
619 mcr |= UART_MCR_RTS;
\r
620 mcr |= UART_MCR_AFE;
\r
622 spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO, SEL_UART);
\r
623 spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
\r
624 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, SEL_UART);
\r
625 spi_out(port, UART_FCR, 0, SEL_UART);
\r
626 spi_out(port, UART_LCR, UART_LCR_WLEN8, SEL_UART);
\r
627 spi_out(port, UART_LCR, cval | UART_LCR_DLAB, SEL_UART);
\r
628 spi_out(port, UART_DLL, quot & 0xff, SEL_UART);
\r
629 ret = spi_in(port, UART_DLL, SEL_UART)&0xff;
\r
630 printk("%s:quot=0x%x,UART_DLL=0x%x\n",__FUNCTION__,quot,ret);
\r
631 spi_out(port, UART_DLM, quot >> 8, SEL_UART);
\r
632 spi_out(port, UART_LCR, cval, SEL_UART);
\r
633 spi_out(port, UART_FCR, fcr, SEL_UART);
\r
634 spi_out(port, UART_MCR, mcr, SEL_UART);
\r
639 void spi_uart_work_handler(struct work_struct *work)
\r
643 struct spi_fpga_port *port =
\r
644 container_of(work, struct spi_fpga_port, uart.spi_uart_work);
\r
645 printk("*************test spi_uart now***************\n");
\r
646 spi_uart_test_init(port);
\r
647 for(i=0;i<UART_TEST_LEN;i++)
\r
648 buf_test_uart[i] = '0'+i;
\r
649 count = UART_TEST_LEN;
\r
650 #if SPI_UART_TXRX_BUF
\r
651 spi_uart_write_buf(&port->uart, buf_test_uart, count);
\r
655 spi_out(port, UART_TX, buf_test_uart[UART_TEST_LEN-count], SEL_UART);
\r
662 static void spi_testuart_timer(unsigned long data)
\r
664 struct spi_fpga_port *port = (struct spi_fpga_port *)data;
\r
665 port->uart.uart_timer.expires = jiffies + msecs_to_jiffies(1000);
\r
666 add_timer(&port->uart.uart_timer);
\r
667 //schedule_work(&port->gpio.spi_gpio_work);
\r
668 queue_work(port->uart.spi_uart_workqueue, &port->uart.spi_uart_work);
\r
677 * This handles the interrupt from one port.
\r
679 void spi_uart_handle_irq(struct spi_device *spi)
\r
681 struct spi_fpga_port *port = spi_get_drvdata(spi);
\r
682 struct spi_uart *uart = &port->uart;
\r
683 unsigned int uart_iir, lsr;
\r
685 if (unlikely(uart->in_spi_uart_irq == current))
\r
687 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
690 * In a few places spi_uart_handle_irq() is called directly instead of
\r
691 * waiting for the actual interrupt to be raised and the SPI IRQ
\r
692 * thread scheduled in order to reduce latency. However, some
\r
693 * interaction with the tty core may end up calling us back
\r
694 * (serial echo, flow control, etc.) through those same places
\r
695 * causing undesirable effects. Let's stop the recursion here.
\r
698 uart_iir = spi_in(port, UART_IIR, SEL_UART);//
\r
699 if (uart_iir & UART_IIR_NO_INT)
\r
702 DBG("iir=0x%x\n",uart_iir);
\r
704 uart->in_spi_uart_irq = current;
\r
705 lsr = spi_in(port, UART_LSR, SEL_UART);//
\r
706 DBG("lsr=0x%x\n",lsr);
\r
708 if (lsr & UART_LSR_DR)
\r
709 //if (((uart_iir & UART_IIR_RDI) | (uart_iir & UART_IIR_RLSI)) && (lsr & UART_LSR_DR))
\r
711 DBG("Enter::%s,LINE=%d,lsr & UART_LSR_DR************\n",__FUNCTION__,__LINE__);
\r
712 spi_uart_receive_chars(uart, &lsr);
\r
715 //spi_uart_check_modem_status(uart);
\r
718 if (lsr & UART_LSR_THRE)
\r
719 //if ((uart_iir & UART_IIR_THRI)&&(lsr & UART_LSR_THRE))
\r
721 DBG("Enter::%s,LINE=%d,ICE_STATUS_TXF == 0************\n",__FUNCTION__,__LINE__);
\r
722 spi_uart_transmit_chars(uart);
\r
725 uart->in_spi_uart_irq = NULL;
\r
727 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
731 static int spi_uart_startup(struct spi_uart *uart)
\r
733 unsigned long page;
\r
734 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
736 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
738 * Set the TTY IO error marker - we will only clear this
\r
739 * once we have successfully opened the port.
\r
741 set_bit(TTY_IO_ERROR, &uart->tty->flags);
\r
743 /* Initialise and allocate the transmit buffer. */
\r
744 page = __get_free_page(GFP_KERNEL);
\r
748 uart->xmit.buf = (unsigned char *)page;
\r
749 circ_clear(&uart->xmit);
\r
751 //mutex_lock(&port->spi_lock);
\r
754 * Clear the FIFO buffers and disable them.
\r
755 * (they will be reenabled in spi_change_speed())
\r
757 spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO, SEL_UART);
\r
758 spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
\r
759 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, SEL_UART);
\r
760 spi_out(port, UART_FCR, 0, SEL_UART);
\r
763 * Clear the interrupt registers.
\r
765 (void) spi_in(port, UART_LSR, SEL_UART);//
\r
766 (void) spi_in(port, UART_RX, SEL_UART);//
\r
767 (void) spi_in(port, UART_IIR, SEL_UART);//
\r
768 (void) spi_in(port, UART_MSR, SEL_UART);//
\r
771 * Now, initialize the UART
\r
773 spi_out(port, UART_LCR, UART_LCR_WLEN8, SEL_UART);
\r
775 uart->ier = UART_IER_RLSI | UART_IER_RDI;
\r
776 //uart->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
\r
777 uart->mctrl = TIOCM_OUT2;
\r
779 spi_uart_change_speed(uart, uart->tty->termios, NULL);
\r
781 if (uart->tty->termios->c_cflag & CBAUD)
\r
782 spi_uart_set_mctrl(uart, TIOCM_RTS | TIOCM_DTR);
\r
784 if (uart->tty->termios->c_cflag & CRTSCTS)
\r
785 if (!(spi_uart_get_mctrl(uart) & TIOCM_CTS))
\r
786 uart->tty->hw_stopped = 1;
\r
788 clear_bit(TTY_IO_ERROR, &uart->tty->flags);
\r
789 DBG("Enter::%s,LINE=%d,uart->ier=0x%x\n",__FUNCTION__,__LINE__,uart->ier);
\r
790 /* Kick the IRQ handler once while we're still holding the host lock */
\r
791 //spi_uart_handle_irq(port->spi);
\r
792 //mutex_unlock(&port->spi_lock);
\r
796 //free_page((unsigned long)uart->xmit.buf);
\r
800 static void spi_uart_shutdown(struct spi_uart *uart)
\r
802 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
803 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
804 //mutex_lock(&port->spi_lock);
\r
805 spi_uart_stop_rx(uart);
\r
807 /* TODO: wait here for TX FIFO to drain */
\r
809 /* Turn off DTR and RTS early. */
\r
810 if (uart->tty->termios->c_cflag & HUPCL)
\r
811 spi_uart_clear_mctrl(uart, TIOCM_DTR | TIOCM_RTS);
\r
813 /* Disable interrupts from this port */
\r
816 spi_out(port, UART_IER, 0, SEL_UART);
\r
818 spi_uart_clear_mctrl(uart, TIOCM_OUT2);
\r
820 /* Disable break condition and FIFOs. */
\r
821 uart->lcr &= ~UART_LCR_SBC;
\r
822 spi_out(port, UART_LCR, uart->lcr, SEL_UART);
\r
823 spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
\r
824 UART_FCR_CLEAR_RCVR |
\r
825 UART_FCR_CLEAR_XMIT, SEL_UART);
\r
826 spi_out(port, UART_FCR, 0, SEL_UART);
\r
828 //mutex_unlock(&port->spi_lock);
\r
831 /* Free the transmit buffer page. */
\r
832 free_page((unsigned long)uart->xmit.buf);
\r
835 static int spi_uart_open (struct tty_struct *tty, struct file * filp)
\r
837 struct spi_uart *uart;
\r
840 uart = spi_uart_port_get(tty->index);
\r
843 DBG("Enter::%s,LINE=%d,!port\n",__FUNCTION__,__LINE__);
\r
846 DBG("Enter::%s,LINE=%d,tty->index=%d\n",__FUNCTION__,__LINE__,tty->index);
\r
847 mutex_lock(&uart->open_lock);
\r
850 * Make sure not to mess up with a dead port
\r
851 * which has not been closed yet.
\r
853 if (tty->driver_data && tty->driver_data != uart) {
\r
854 mutex_unlock(&uart->open_lock);
\r
855 spi_uart_port_put(uart);
\r
856 DBG("Enter::%s,LINE=%d,!= uart\n",__FUNCTION__,__LINE__);
\r
860 if (!uart->opened) {
\r
861 tty->driver_data = uart;
\r
863 ret = spi_uart_startup(uart);
\r
865 tty->driver_data = NULL;
\r
867 mutex_unlock(&uart->open_lock);
\r
868 spi_uart_port_put(uart);
\r
869 DBG("Enter::%s,LINE=%d,ret=%d\n",__FUNCTION__,__LINE__,ret);
\r
874 DBG("Enter::%s,uart->opened++=%d\n",__FUNCTION__,uart->opened);
\r
875 mutex_unlock(&uart->open_lock);
\r
879 static void spi_uart_close(struct tty_struct *tty, struct file * filp)
\r
881 struct spi_uart *uart = tty->driver_data;
\r
882 printk("Enter::%s,LINE=%d,tty->hw_stopped=%d\n",__FUNCTION__,__LINE__,tty->hw_stopped);
\r
886 mutex_lock(&uart->open_lock);
\r
887 BUG_ON(!uart->opened);
\r
890 * This is messy. The tty layer calls us even when open()
\r
891 * returned an error. Ignore this close request if tty->count
\r
892 * is larger than uart->count.
\r
894 if (tty->count > uart->opened) {
\r
895 mutex_unlock(&uart->open_lock);
\r
899 if (--uart->opened == 0) {
\r
900 DBG("Enter::%s,opened=%d\n",__FUNCTION__,uart->opened);
\r
902 spi_uart_shutdown(uart);
\r
903 tty_ldisc_flush(tty);
\r
905 tty->driver_data = NULL;
\r
908 spi_uart_port_put(uart);
\r
909 mutex_unlock(&uart->open_lock);
\r
913 static int spi_uart_write(struct tty_struct * tty, const unsigned char *buf,
\r
916 struct spi_uart *uart = tty->driver_data;
\r
917 struct circ_buf *circ = &uart->xmit;
\r
918 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
923 printk("spi error!!!!\n");
\r
928 DBG("spi_uart_write 1 circ->head=%d,circ->tail=%d\n",circ->head,circ->tail);
\r
930 spin_lock(&uart->write_lock);
\r
932 c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
\r
937 memcpy(circ->buf + circ->head, buf, c);
\r
938 circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
\r
943 spin_unlock(&uart->write_lock);
\r
946 if ( !(uart->ier & UART_IER_THRI)) {
\r
947 //mutex_lock(&port->spi_lock);
\r
948 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
949 /*Note:ICE65L08 output a 'Transmitter holding register interrupt' after 1us*/
\r
951 spi_uart_start_tx(uart);
\r
952 spi_uart_handle_irq(port->spi);
\r
953 //mutex_unlock(&port->spi_lock);
\r
957 //printk("w%d\n",ret);
\r
961 static int spi_uart_write_room(struct tty_struct *tty)
\r
963 struct spi_uart *uart = tty->driver_data;
\r
964 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
965 return uart ? circ_chars_free(&uart->xmit) : 0;
\r
968 static int spi_uart_chars_in_buffer(struct tty_struct *tty)
\r
970 struct spi_uart *uart = tty->driver_data;
\r
971 printk("Enter::%s,LINE=%d,circ=%ld****\n",__FUNCTION__,__LINE__,circ_chars_pending(&uart->xmit));
\r
972 return uart ? circ_chars_pending(&uart->xmit) : 0;
\r
975 static void spi_uart_send_xchar(struct tty_struct *tty, char ch)
\r
977 struct spi_uart *uart = tty->driver_data;
\r
978 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
979 printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
981 if (ch && !(uart->ier & UART_IER_THRI)) {
\r
982 //mutex_lock(&port->spi_lock);
\r
983 spi_uart_start_tx(uart);
\r
984 printk("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
985 spi_uart_handle_irq(port->spi);
\r
986 //mutex_unlock(&port->spi_lock);
\r
990 static void spi_uart_throttle(struct tty_struct *tty)
\r
992 struct spi_uart *uart = tty->driver_data;
\r
993 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
994 printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
995 if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))
\r
997 printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
998 //mutex_lock(&port->spi_lock);
\r
999 if (I_IXOFF(tty)) {
\r
1000 uart->x_char = STOP_CHAR(tty);
\r
1001 spi_uart_start_tx(uart);
\r
1002 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
1005 if (tty->termios->c_cflag & CRTSCTS)
\r
1006 spi_uart_clear_mctrl(uart, TIOCM_RTS);
\r
1008 spi_uart_handle_irq(port->spi);
\r
1009 //mutex_unlock(&port->spi_lock);
\r
1012 static void spi_uart_unthrottle(struct tty_struct *tty)
\r
1014 struct spi_uart *uart = tty->driver_data;
\r
1015 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
1016 printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1017 if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))
\r
1019 //mutex_lock(&port->spi_lock);
\r
1020 if (I_IXOFF(tty)) {
\r
1021 if (uart->x_char) {
\r
1024 uart->x_char = START_CHAR(tty);
\r
1025 spi_uart_start_tx(uart);
\r
1026 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
1030 if (tty->termios->c_cflag & CRTSCTS)
\r
1031 spi_uart_set_mctrl(uart, TIOCM_RTS);
\r
1033 spi_uart_handle_irq(port->spi);
\r
1034 //mutex_unlock(&port->spi_lock);
\r
1037 static void spi_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
\r
1039 struct spi_uart *uart = tty->driver_data;
\r
1040 unsigned int cflag = tty->termios->c_cflag;
\r
1041 unsigned int mask = TIOCM_DTR;
\r
1042 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1044 #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
\r
1046 if ((cflag ^ old_termios->c_cflag) == 0 &&
\r
1047 RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
\r
1050 //mutex_lock(&port->spi_lock);
\r
1051 spi_uart_change_speed(uart, tty->termios, old_termios);
\r
1053 /* Handle transition to B0 status */
\r
1054 if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)){
\r
1055 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1056 spi_uart_clear_mctrl(uart, TIOCM_RTS | TIOCM_DTR);
\r
1057 //spi_uart_clear_mctrl(uart, TIOCM_RTS);
\r
1060 /* Handle transition away from B0 status */
\r
1061 if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
\r
1062 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1063 if (!(cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags))
\r
1064 mask |= TIOCM_RTS;
\r
1065 spi_uart_set_mctrl(uart, mask);
\r
1068 /* Handle turning off CRTSCTS */
\r
1069 if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
\r
1070 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1071 tty->hw_stopped = 0;
\r
1072 spi_uart_start_tx(uart);
\r
1073 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
1076 /* Handle turning on CRTSCTS */
\r
1077 if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
\r
1078 DBG("Enter::%s,LINE=%d,status=0x%x,Handle turning on CRTSCTS*****************\n",__FUNCTION__,__LINE__,spi_uart_get_mctrl(uart));
\r
1079 //spi_uart_set_mctrl(uart, TIOCM_RTS);
\r
1080 if (!(spi_uart_get_mctrl(uart) & TIOCM_CTS)) {
\r
1081 DBG("Enter::%s,LINE=%d,tty->hw_stopped = 1********\n",__FUNCTION__,__LINE__);
\r
1082 tty->hw_stopped = 1;
\r
1083 spi_uart_stop_tx(uart);
\r
1086 //mutex_unlock(&port->spi_lock);
\r
1090 static int spi_uart_break_ctl(struct tty_struct *tty, int break_state)
\r
1092 struct spi_uart *uart = tty->driver_data;
\r
1093 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
1094 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1095 //mutex_lock(&port->spi_lock);
\r
1096 if (break_state == -1)
\r
1097 uart->lcr |= UART_LCR_SBC;
\r
1099 uart->lcr &= ~UART_LCR_SBC;
\r
1100 spi_out(port, UART_LCR, uart->lcr, SEL_UART);
\r
1101 //mutex_unlock(&port->spi_lock);
\r
1105 static int spi_uart_tiocmget(struct tty_struct *tty, struct file *file)
\r
1107 struct spi_uart *uart = tty->driver_data;
\r
1109 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1110 //mutex_lock(&port->spi_lock);
\r
1111 result = uart->mctrl | spi_uart_get_mctrl(uart);
\r
1112 //mutex_unlock(&port->spi_lock);
\r
1116 static int spi_uart_tiocmset(struct tty_struct *tty, struct file *file,
\r
1117 unsigned int set, unsigned int clear)
\r
1119 struct spi_uart *uart = tty->driver_data;
\r
1120 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1121 //mutex_lock(&port->spi_lock);
\r
1122 spi_uart_update_mctrl(uart, set, clear);
\r
1123 //mutex_unlock(&port->spi_lock);
\r
1129 static int spi_uart_read_proc(char *page, char **start, off_t off,
\r
1130 int count, int *eof, void *data)
\r
1134 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1135 len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n",
\r
1137 for (i = 0; i < UART_NR && len < PAGE_SIZE - 96; i++) {
\r
1138 struct spi_uart *uart = spi_uart_port_get(i);
\r
1140 len += sprintf(page+len, "%d: uart:SPI", i);
\r
1141 if(capable(CAP_SYS_ADMIN)) {
\r
1142 len += sprintf(page + len, " tx:%d rx:%d",
\r
1143 uart->icount.tx, uart->icount.rx);
\r
1144 if (uart->icount.frame)
\r
1145 len += sprintf(page + len, " fe:%d",
\r
1146 uart->icount.frame);
\r
1147 if (uart->icount.parity)
\r
1148 len += sprintf(page + len, " pe:%d",
\r
1149 uart->icount.parity);
\r
1150 if (uart->icount.brk)
\r
1151 len += sprintf(page + len, " brk:%d",
\r
1152 uart->icount.brk);
\r
1153 if (uart->icount.overrun)
\r
1154 len += sprintf(page + len, " oe:%d",
\r
1155 uart->icount.overrun);
\r
1156 if (uart->icount.cts)
\r
1157 len += sprintf(page + len, " cts:%d",
\r
1158 uart->icount.cts);
\r
1159 if (uart->icount.dsr)
\r
1160 len += sprintf(page + len, " dsr:%d",
\r
1161 uart->icount.dsr);
\r
1162 if (uart->icount.rng)
\r
1163 len += sprintf(page + len, " rng:%d",
\r
1164 uart->icount.rng);
\r
1165 if (uart->icount.dcd)
\r
1166 len += sprintf(page + len, " dcd:%d",
\r
1167 uart->icount.dcd);
\r
1169 strcat(page, "\n");
\r
1171 spi_uart_port_put(uart);
\r
1174 if (len + begin > off + count)
\r
1176 if (len + begin < off) {
\r
1184 if (off >= len + begin)
\r
1186 *start = page + (off - begin);
\r
1187 return (count < begin + len - off) ? count : (begin + len - off);
\r
1191 static const struct tty_operations spi_uart_ops = {
\r
1192 .open = spi_uart_open,
\r
1193 .close = spi_uart_close,
\r
1194 .write = spi_uart_write,
\r
1195 .write_room = spi_uart_write_room,
\r
1196 .chars_in_buffer = spi_uart_chars_in_buffer,
\r
1197 .send_xchar = spi_uart_send_xchar,
\r
1198 .throttle = spi_uart_throttle,
\r
1199 .unthrottle = spi_uart_unthrottle,
\r
1200 .set_termios = spi_uart_set_termios,
\r
1201 .break_ctl = spi_uart_break_ctl,
\r
1202 .tiocmget = spi_uart_tiocmget,
\r
1203 .tiocmset = spi_uart_tiocmset,
\r
1204 //.read_proc = spi_uart_read_proc,
\r
1208 static struct tty_driver *spi_uart_tty_driver;
\r
1210 int spi_uart_register(struct spi_fpga_port *port)
\r
1213 struct tty_driver *tty_drv;
\r
1214 spi_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);
\r
1217 tty_drv->owner = THIS_MODULE;
\r
1218 tty_drv->driver_name = "spi_uart";
\r
1219 tty_drv->name = "ttySPI";
\r
1220 tty_drv->major = 0; /* dynamically allocated */
\r
1221 tty_drv->minor_start = 0;
\r
1222 //tty_drv->num = UART_NR;
\r
1223 tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
\r
1224 tty_drv->subtype = SERIAL_TYPE_NORMAL;
\r
1225 tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
\r
1226 tty_drv->init_termios = tty_std_termios;
\r
1227 tty_drv->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
\r
1228 tty_drv->init_termios.c_ispeed = 115200;
\r
1229 tty_drv->init_termios.c_ospeed = 115200;
\r
1230 tty_set_operations(tty_drv, &spi_uart_ops);
\r
1232 ret = tty_register_driver(tty_drv);
\r
1236 //port->uart.uartclk = 64*115200; //MCLK/4
\r
1237 port->uart.uartclk = 60*100000; //MCLK/4
\r
1239 for(i=0; i<UART_NR; i++)
\r
1241 ret = spi_uart_add_port(&port->uart);
\r
1245 struct device *dev;
\r
1246 dev = tty_register_device(spi_uart_tty_driver, port->uart.index, &port->spi->dev);
\r
1247 if (IS_ERR(dev)) {
\r
1248 spi_uart_port_remove(&port->uart);
\r
1249 ret = PTR_ERR(dev);
\r
1257 sprintf(b, "spi_uart_workqueue");
\r
1258 port->uart.spi_uart_workqueue = create_freezeable_workqueue(b);
\r
1259 if (!port->uart.spi_uart_workqueue) {
\r
1260 printk("cannot create workqueue\n");
\r
1263 INIT_WORK(&port->uart.spi_uart_work, spi_uart_work_handler);
\r
1265 setup_timer(&port->uart.uart_timer, spi_testuart_timer, (unsigned long)port);
\r
1266 port->uart.uart_timer.expires = jiffies+2000;
\r
1267 add_timer(&port->uart.uart_timer);
\r
1275 tty_unregister_driver(tty_drv);
\r
1277 put_tty_driver(tty_drv);
\r
1283 int spi_uart_unregister(struct spi_fpga_port *port)
\r
1289 MODULE_DESCRIPTION("Driver for spi2uart.");
\r
1290 MODULE_AUTHOR("luowei <lw@rock-chips.com>");
\r
1291 MODULE_LICENSE("GPL");
\r