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 "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 static struct tty_driver *spi_uart_tty_driver;
\r
41 /*------------------------ÒÔÏÂÊÇspi2uart±äÁ¿-----------------------*/
\r
43 #define UART_NR 1 /* Number of UARTs this driver can handle */
\r
45 #define UART_XMIT_SIZE PAGE_SIZE
\r
46 #define WAKEUP_CHARS 1024
\r
48 #define circ_empty(circ) ((circ)->head == (circ)->tail)
\r
49 #define circ_clear(circ) ((circ)->head = (circ)->tail = 0)
\r
51 #define circ_chars_pending(circ) \
\r
52 (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
\r
54 #define circ_chars_free(circ) \
\r
55 (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
\r
60 static struct spi_uart *spi_uart_table[UART_NR];
\r
61 static DEFINE_SPINLOCK(spi_uart_table_lock);
\r
64 static int spi_uart_add_port(struct spi_uart *uart)
\r
66 int index, ret = -EBUSY;
\r
68 kref_init(&uart->kref);
\r
69 mutex_init(&uart->open_lock);
\r
70 spin_lock_init(&uart->write_lock);
\r
71 spin_lock_init(&uart->irq_lock);
\r
73 spin_lock(&spi_uart_table_lock);
\r
74 for (index = 0; index < UART_NR; index++)
\r
76 if (!spi_uart_table[index]) {
\r
77 uart->index = index;
\r
78 //printk("index=%d\n\n",index);
\r
79 spi_uart_table[index] = uart;
\r
84 spin_unlock(&spi_uart_table_lock);
\r
89 static struct spi_uart *spi_uart_port_get(unsigned index)
\r
91 struct spi_uart *uart;
\r
93 if (index >= UART_NR)
\r
96 spin_lock(&spi_uart_table_lock);
\r
97 uart = spi_uart_table[index];
\r
98 uart->index = index;
\r
99 printk("uart->index=%d\n",uart->index);
\r
101 kref_get(&uart->kref);
\r
102 spin_unlock(&spi_uart_table_lock);
\r
107 static void spi_uart_port_destroy(struct kref *kref)
\r
109 struct spi_uart *uart =
\r
110 container_of(kref, struct spi_uart, kref);
\r
114 static void spi_uart_port_put(struct spi_uart *uart)
\r
116 kref_put(&uart->kref, spi_uart_port_destroy);
\r
119 static void spi_uart_port_remove(struct spi_uart *uart)
\r
121 struct spi_device *spi;
\r
122 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
124 BUG_ON(spi_uart_table[uart->index] != uart);
\r
126 spin_lock(&spi_uart_table_lock);
\r
127 spi_uart_table[uart->index] = NULL;
\r
128 spin_unlock(&spi_uart_table_lock);
\r
131 * We're killing a port that potentially still is in use by
\r
132 * the tty layer. Be careful to arrange for the tty layer to
\r
133 * give up on that port ASAP.
\r
134 * Beware: the lock ordering is critical.
\r
136 mutex_lock(&uart->open_lock);
\r
137 //mutex_lock(&port->spi_lock);
\r
141 //mutex_unlock(&port->spi_lock);
\r
143 tty_hangup(uart->tty);
\r
144 mutex_unlock(&uart->open_lock);
\r
146 spi_uart_port_put(uart);
\r
149 static unsigned int spi_uart_get_mctrl(struct spi_uart *uart)
\r
151 unsigned char status;
\r
153 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
155 status = spi_in(port, UART_MSR, SEL_UART);//
\r
158 if (status & UART_MSR_DCD)
\r
160 if (status & UART_MSR_RI)
\r
162 if (status & UART_MSR_DSR)
\r
164 if (status & UART_MSR_CTS)
\r
167 if (status & UART_MSR_CTS)
\r
168 ret = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
\r
169 DBG("Enter::%s,LINE=%d,ret=0x%x************************\n",__FUNCTION__,__LINE__,ret);
\r
173 static void spi_uart_write_mctrl(struct spi_uart *uart, unsigned int mctrl)
\r
175 unsigned char mcr = 0;
\r
176 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
178 if (mctrl & TIOCM_RTS)
\r
180 mcr |= UART_MCR_RTS;
\r
181 mcr |= UART_MCR_AFE;
\r
183 //if (mctrl & TIOCM_DTR)
\r
184 // mcr |= UART_MCR_DTR;
\r
185 //if (mctrl & TIOCM_OUT1)
\r
186 // mcr |= UART_MCR_OUT1;
\r
187 //if (mctrl & TIOCM_OUT2)
\r
188 // mcr |= UART_MCR_OUT2;
\r
189 //if (mctrl & TIOCM_LOOP)
\r
190 // mcr |= UART_MCR_LOOP;
\r
194 DBG("Enter::%s,LINE=%d,mcr=0x%x\n",__FUNCTION__,__LINE__,mcr);
\r
195 spi_out(port, UART_MCR, mcr, SEL_UART);
\r
198 static inline void spi_uart_update_mctrl(struct spi_uart *uart,
\r
199 unsigned int set, unsigned int clear)
\r
202 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
204 uart->mctrl = (old & ~clear) | set;
\r
205 if (old != uart->mctrl)
\r
206 spi_uart_write_mctrl(uart, uart->mctrl);
\r
209 #define spi_uart_set_mctrl(uart, x) spi_uart_update_mctrl(uart, x, 0)
\r
210 #define spi_uart_clear_mctrl(uart, x) spi_uart_update_mctrl(uart, 0, x)
\r
212 static void spi_uart_change_speed(struct spi_uart *uart,
\r
213 struct ktermios *termios,
\r
214 struct ktermios *old)
\r
216 unsigned char cval, fcr = 0;
\r
217 unsigned int baud, quot;
\r
218 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
220 switch (termios->c_cflag & CSIZE) {
\r
222 cval = UART_LCR_WLEN5;
\r
225 cval = UART_LCR_WLEN6;
\r
228 cval = UART_LCR_WLEN7;
\r
232 cval = UART_LCR_WLEN8;
\r
236 if (termios->c_cflag & CSTOPB)
\r
237 cval |= UART_LCR_STOP;
\r
238 if (termios->c_cflag & PARENB)
\r
239 cval |= UART_LCR_PARITY;
\r
240 if (!(termios->c_cflag & PARODD))
\r
241 cval |= UART_LCR_EPAR;
\r
244 baud = tty_termios_baud_rate(termios);
\r
246 baud = 115200; /* Special case: B0 rate. */
\r
247 if (baud <= uart->uartclk)
\r
250 * Oops, the quotient was zero. Try again with the old
\r
251 * baud rate if possible, otherwise default to 115200.
\r
253 termios->c_cflag &= ~CBAUD;
\r
255 termios->c_cflag |= old->c_cflag & CBAUD;
\r
258 termios->c_cflag |= B115200;
\r
260 //quot = (2 * uart->uartclk + baud) / (2 * baud);
\r
261 quot = (uart->uartclk / baud);
\r
262 printk("baud=%d,quot=0x%x\n",baud,quot);
\r
264 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
\r
266 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
\r
268 uart->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
\r
269 if (termios->c_iflag & INPCK)
\r
270 uart->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
\r
271 if (termios->c_iflag & (BRKINT | PARMRK))
\r
272 uart->read_status_mask |= UART_LSR_BI;
\r
275 * Characters to ignore
\r
277 uart->ignore_status_mask = 0;
\r
278 if (termios->c_iflag & IGNPAR)
\r
279 uart->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
\r
280 if (termios->c_iflag & IGNBRK) {
\r
281 uart->ignore_status_mask |= UART_LSR_BI;
\r
283 * If we're ignoring parity and break indicators,
\r
284 * ignore overruns too (for real raw support).
\r
286 if (termios->c_iflag & IGNPAR)
\r
287 uart->ignore_status_mask |= UART_LSR_OE;
\r
291 * ignore all characters if CREAD is not set
\r
293 if ((termios->c_cflag & CREAD) == 0)
\r
294 uart->ignore_status_mask |= UART_LSR_DR;
\r
297 * CTS flow control flag and modem status interrupts
\r
299 uart->ier &= ~UART_IER_MSI;
\r
300 if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))
\r
302 //uart->ier |= UART_IER_MSI;
\r
303 //uart->mcr = UART_MCR_RTS;//mcr = UART_MCR_RTS while start RTSCTS
\r
308 spi_out(port, UART_IER, uart->ier, SEL_UART);
\r
309 spi_out(port, UART_LCR, cval | UART_LCR_DLAB, SEL_UART);
\r
310 spi_out(port, UART_DLL, quot & 0xff, SEL_UART);
\r
311 spi_out(port, UART_DLM, quot >> 8, SEL_UART);
\r
312 spi_out(port, UART_LCR, cval, SEL_UART);
\r
313 spi_out(port, UART_FCR, fcr, SEL_UART);
\r
314 DBG("Enter::%s,LINE=%d,baud=%d,uart->ier=0x%x,cval=0x%x,fcr=0x%x,quot=0x%x\n",
\r
315 __FUNCTION__,__LINE__,baud,uart->ier,cval,fcr,quot);
\r
316 spi_uart_write_mctrl(uart, uart->mctrl);
\r
319 static void spi_uart_start_tx(struct spi_uart *uart)
\r
321 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
323 //unsigned long flags;
\r
324 if (!(uart->ier & UART_IER_THRI)) {
\r
325 //spin_lock_irqsave(&uart->write_lock, flags);
\r
326 uart->ier |= UART_IER_THRI;
\r
327 spi_out(port, UART_IER, uart->ier, SEL_UART);
\r
328 //spin_unlock_irqrestore(&uart->write_lock, flags);
\r
332 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
336 static void spi_uart_stop_tx(struct spi_uart *uart)
\r
338 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
339 //unsigned long flags;
\r
340 if (uart->ier & UART_IER_THRI) {
\r
341 //spin_lock_irqsave(&uart->write_lock, flags);
\r
342 uart->ier &= ~UART_IER_THRI;
\r
343 spi_out(port, UART_IER, uart->ier, SEL_UART);
\r
344 //spin_unlock_irqrestore(&uart->write_lock, flags);
\r
347 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
350 static void spi_uart_stop_rx(struct spi_uart *uart)
\r
352 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
353 uart->ier &= ~UART_IER_RLSI;
\r
354 uart->read_status_mask &= ~UART_LSR_DR;
\r
355 spi_out(port, UART_IER, uart->ier, SEL_UART);
\r
358 static void spi_uart_receive_chars(struct spi_uart *uart, unsigned int *status)
\r
360 struct tty_struct *tty = uart->tty;
\r
361 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
363 unsigned int ch, flag;
\r
364 int max_count = 1024;
\r
366 while (--max_count >0 )
\r
368 ch = spi_in(port, UART_RX, SEL_UART);//
\r
369 //printk("0x%x,",ch&0xff);
\r
374 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
\r
375 UART_LSR_FE | UART_LSR_OE))) {
\r
377 * For statistics only
\r
379 if (*status & UART_LSR_BI) {
\r
380 *status &= ~(UART_LSR_FE | UART_LSR_PE);
\r
381 uart->icount.brk++;
\r
382 } else if (*status & UART_LSR_PE)
\r
383 uart->icount.parity++;
\r
384 else if (*status & UART_LSR_FE)
\r
385 uart->icount.frame++;
\r
386 if (*status & UART_LSR_OE)
\r
387 uart->icount.overrun++;
\r
390 * Mask off conditions which should be ignored.
\r
392 *status &= uart->read_status_mask;
\r
393 if (*status & UART_LSR_BI) {
\r
395 } else if (*status & UART_LSR_PE)
\r
397 else if (*status & UART_LSR_FE)
\r
401 if ((*status & uart->ignore_status_mask & ~UART_LSR_OE) == 0)
\r
402 tty_insert_flip_char(tty, ch, flag);
\r
405 * Overrun is special. Since it's reported immediately,
\r
406 * it doesn't affect the current character.
\r
408 if (*status & ~uart->ignore_status_mask & UART_LSR_OE)
\r
409 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
\r
410 *status = spi_in(port, UART_LSR, SEL_UART);
\r
411 if(!(*status & UART_LSR_DR))
\r
415 DBG("Enter::%s,LINE=%d,rx_count=%d********\n",__FUNCTION__,__LINE__,(1024-max_count));
\r
416 printk("r%d\n",1024-max_count);
\r
417 tty_flip_buffer_push(tty);
\r
421 static void spi_uart_transmit_chars(struct spi_uart *uart)
\r
423 struct circ_buf *xmit = &uart->xmit;
\r
425 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
427 if (uart->x_char) {
\r
428 spi_out(port, UART_TX, uart->x_char, SEL_UART);
\r
431 printk("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
434 if (circ_empty(xmit) || uart->tty->stopped || uart->tty->hw_stopped) {
\r
435 spi_uart_stop_tx(uart);
\r
436 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
437 //printk("circ_empty()\n");
\r
444 spi_out(port, UART_TX, xmit->buf[xmit->tail], SEL_UART);
\r
445 //printk("0x%x,",xmit->buf[xmit->tail]);
\r
446 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
\r
449 if (circ_empty(xmit))
\r
454 DBG("Enter::%s,LINE=%d,tx_count=%d\n",__FUNCTION__,__LINE__,(32-count));
\r
455 if (circ_chars_pending(xmit) < WAKEUP_CHARS)
\r
457 tty_wakeup(uart->tty);
\r
460 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
461 if (circ_empty(xmit))
\r
463 DBG("circ_empty(xmit)\n");
\r
464 spi_uart_stop_tx(uart);
\r
468 printk("t%d\n",32-count);
\r
470 DBG("uart->tty->hw_stopped = %d\n",uart->tty->hw_stopped);
\r
474 static void spi_uart_check_modem_status(struct spi_uart *uart)
\r
477 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
479 status = spi_in(port, UART_MSR, SEL_UART);//
\r
480 DBG("Enter::%s,LINE=%d,status=0x%x*******\n",__FUNCTION__,__LINE__,status);
\r
481 if ((status & UART_MSR_ANY_DELTA) == 0)
\r
484 if (status & UART_MSR_TERI)
\r
485 uart->icount.rng++;
\r
486 if (status & UART_MSR_DDSR)
\r
487 uart->icount.dsr++;
\r
488 if (status & UART_MSR_DDCD)
\r
489 uart->icount.dcd++;
\r
490 if (status & UART_MSR_DCTS) {
\r
491 uart->icount.cts++;
\r
492 if (uart->tty->termios->c_cflag & CRTSCTS) {
\r
493 int cts = (status & UART_MSR_CTS);
\r
494 if (uart->tty->hw_stopped) {
\r
496 uart->tty->hw_stopped = 0;
\r
497 spi_uart_start_tx(uart);
\r
498 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
499 tty_wakeup(uart->tty);
\r
503 uart->tty->hw_stopped = 1;
\r
504 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
505 spi_uart_stop_tx(uart);
\r
510 DBG("Enter::%s,LINE=%d,status=0x%x*******\n",__FUNCTION__,__LINE__,status);
\r
516 #define UART_TEST_LEN 16 //8bit
\r
517 unsigned char buf_test_uart[UART_TEST_LEN];
\r
518 unsigned int ice65l08_init_para[]=
\r
522 0x000034, // (0100XYH) ÉèÖ÷ÖƵϵÊý£ºXY = MCLK / (4*²¨ÌØÂÊ)£»
\r
523 0x030003, // ÉèÖÃ×Ö½ÚÓÐЧ³¤¶È£º 8 bits£»
\r
524 0x01000f, // TX RX ÖжÏ
\r
525 0x020080, // ÉèÖô¥·¢µÈ¼¶ ½ÓÊÜFIFOΪ 16bytes ²úÉúÖжϣ»
\r
528 void spi_uart_work_handler(struct work_struct *work)
\r
533 struct spi_fpga_port *port =
\r
534 container_of(work, struct spi_fpga_port, uart.spi_uart_work);
\r
535 printk("*************test spi_uart now***************\n");
\r
537 for(i=0;i<UART_TEST_LEN;i++)
\r
538 buf_test_uart[i] = '0'+i;
\r
540 for(i =0; i<sizeof(ice65l08_init_para)/sizeof(ice65l08_init_para[0]); i++)
\r
542 offset = (ice65l08_init_para[i] >> 16) & 0xff;
\r
543 value = ice65l08_init_para[i] & 0xffff;
\r
544 spi_out(port, offset, value, SEL_UART);
\r
547 count = UART_TEST_LEN;
\r
550 spi_out(port, UART_TX, buf_test_uart[UART_TEST_LEN-count], SEL_UART);
\r
555 static void spi_testuart_timer(unsigned long data)
\r
557 struct spi_fpga_port *port = (struct spi_fpga_port *)data;
\r
558 port->uart.uart_timer.expires = jiffies + msecs_to_jiffies(1000);
\r
559 add_timer(&port->uart.uart_timer);
\r
560 //schedule_work(&port->gpio.spi_gpio_work);
\r
561 queue_work(port->uart.spi_uart_workqueue, &port->uart.spi_uart_work);
\r
570 * This handles the interrupt from one port.
\r
572 void spi_uart_handle_irq(struct spi_device *spi)
\r
574 struct spi_fpga_port *port = spi_get_drvdata(spi);
\r
575 struct spi_uart *uart = &port->uart;
\r
576 unsigned int uart_iir, lsr;
\r
578 if (unlikely(uart->in_spi_uart_irq == current))
\r
580 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
583 * In a few places spi_uart_handle_irq() is called directly instead of
\r
584 * waiting for the actual interrupt to be raised and the SPI IRQ
\r
585 * thread scheduled in order to reduce latency. However, some
\r
586 * interaction with the tty core may end up calling us back
\r
587 * (serial echo, flow control, etc.) through those same places
\r
588 * causing undesirable effects. Let's stop the recursion here.
\r
591 uart_iir = spi_in(port, UART_IIR, SEL_UART);//
\r
592 if (uart_iir & UART_IIR_NO_INT)
\r
595 DBG("iir=0x%x\n",uart_iir);
\r
597 uart->in_spi_uart_irq = current;
\r
598 lsr = spi_in(port, UART_LSR, SEL_UART);//
\r
599 DBG("lsr=0x%x\n",lsr);
\r
601 if (lsr & UART_LSR_DR)
\r
602 //if (((uart_iir & UART_IIR_RDI) | (uart_iir & UART_IIR_RLSI)) && (lsr & UART_LSR_DR))
\r
604 DBG("Enter::%s,LINE=%d,lsr & UART_LSR_DR************\n",__FUNCTION__,__LINE__);
\r
605 spi_uart_receive_chars(uart, &lsr);
\r
608 //spi_uart_check_modem_status(uart);
\r
611 if (lsr & UART_LSR_THRE)
\r
612 //if ((uart_iir & UART_IIR_THRI)&&(lsr & UART_LSR_THRE))
\r
614 DBG("Enter::%s,LINE=%d,ICE_STATUS_TXF == 0************\n",__FUNCTION__,__LINE__);
\r
615 spi_uart_transmit_chars(uart);
\r
618 uart->in_spi_uart_irq = NULL;
\r
620 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
624 static int spi_uart_startup(struct spi_uart *uart)
\r
626 unsigned long page;
\r
627 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
629 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
631 * Set the TTY IO error marker - we will only clear this
\r
632 * once we have successfully opened the port.
\r
634 set_bit(TTY_IO_ERROR, &uart->tty->flags);
\r
636 /* Initialise and allocate the transmit buffer. */
\r
637 page = __get_free_page(GFP_KERNEL);
\r
641 uart->xmit.buf = (unsigned char *)page;
\r
642 circ_clear(&uart->xmit);
\r
644 //mutex_lock(&port->spi_lock);
\r
647 * Clear the FIFO buffers and disable them.
\r
648 * (they will be reenabled in spi_change_speed())
\r
650 spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO, SEL_UART);
\r
651 spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
\r
652 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, SEL_UART);
\r
653 spi_out(port, UART_FCR, 0, SEL_UART);
\r
656 * Clear the interrupt registers.
\r
658 (void) spi_in(port, UART_LSR, SEL_UART);//
\r
659 (void) spi_in(port, UART_RX, SEL_UART);//
\r
660 (void) spi_in(port, UART_IIR, SEL_UART);//
\r
661 (void) spi_in(port, UART_MSR, SEL_UART);//
\r
664 * Now, initialize the UART
\r
666 spi_out(port, UART_LCR, UART_LCR_WLEN8, SEL_UART);
\r
668 uart->ier = UART_IER_RLSI | UART_IER_RDI;
\r
669 //uart->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE;
\r
670 uart->mctrl = TIOCM_OUT2;
\r
672 spi_uart_change_speed(uart, uart->tty->termios, NULL);
\r
674 if (uart->tty->termios->c_cflag & CBAUD)
\r
675 spi_uart_set_mctrl(uart, TIOCM_RTS | TIOCM_DTR);
\r
677 if (uart->tty->termios->c_cflag & CRTSCTS)
\r
678 if (!(spi_uart_get_mctrl(uart) & TIOCM_CTS))
\r
679 uart->tty->hw_stopped = 1;
\r
681 clear_bit(TTY_IO_ERROR, &uart->tty->flags);
\r
682 DBG("Enter::%s,LINE=%d,uart->ier=0x%x\n",__FUNCTION__,__LINE__,uart->ier);
\r
683 /* Kick the IRQ handler once while we're still holding the host lock */
\r
684 //spi_uart_handle_irq(port->spi);
\r
685 //mutex_unlock(&port->spi_lock);
\r
689 //free_page((unsigned long)uart->xmit.buf);
\r
693 static void spi_uart_shutdown(struct spi_uart *uart)
\r
695 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
696 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
697 //mutex_lock(&port->spi_lock);
\r
698 spi_uart_stop_rx(uart);
\r
700 /* TODO: wait here for TX FIFO to drain */
\r
702 /* Turn off DTR and RTS early. */
\r
703 if (uart->tty->termios->c_cflag & HUPCL)
\r
704 spi_uart_clear_mctrl(uart, TIOCM_DTR | TIOCM_RTS);
\r
706 /* Disable interrupts from this port */
\r
709 spi_out(port, UART_IER, 0, SEL_UART);
\r
711 spi_uart_clear_mctrl(uart, TIOCM_OUT2);
\r
713 /* Disable break condition and FIFOs. */
\r
714 uart->lcr &= ~UART_LCR_SBC;
\r
715 spi_out(port, UART_LCR, uart->lcr, SEL_UART);
\r
716 spi_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
\r
717 UART_FCR_CLEAR_RCVR |
\r
718 UART_FCR_CLEAR_XMIT, SEL_UART);
\r
719 spi_out(port, UART_FCR, 0, SEL_UART);
\r
721 //mutex_unlock(&port->spi_lock);
\r
724 /* Free the transmit buffer page. */
\r
725 free_page((unsigned long)uart->xmit.buf);
\r
728 static int spi_uart_open (struct tty_struct *tty, struct file * filp)
\r
730 struct spi_uart *uart;
\r
733 uart = spi_uart_port_get(tty->index);
\r
736 DBG("Enter::%s,LINE=%d,!port\n",__FUNCTION__,__LINE__);
\r
739 DBG("Enter::%s,LINE=%d,tty->index=%d\n",__FUNCTION__,__LINE__,tty->index);
\r
740 mutex_lock(&uart->open_lock);
\r
743 * Make sure not to mess up with a dead port
\r
744 * which has not been closed yet.
\r
746 if (tty->driver_data && tty->driver_data != uart) {
\r
747 mutex_unlock(&uart->open_lock);
\r
748 spi_uart_port_put(uart);
\r
749 DBG("Enter::%s,LINE=%d,!= uart\n",__FUNCTION__,__LINE__);
\r
753 if (!uart->opened) {
\r
754 tty->driver_data = uart;
\r
756 ret = spi_uart_startup(uart);
\r
758 tty->driver_data = NULL;
\r
760 mutex_unlock(&uart->open_lock);
\r
761 spi_uart_port_put(uart);
\r
762 DBG("Enter::%s,LINE=%d,ret=%d\n",__FUNCTION__,__LINE__,ret);
\r
767 DBG("Enter::%s,uart->opened++=%d\n",__FUNCTION__,uart->opened);
\r
768 mutex_unlock(&uart->open_lock);
\r
772 static void spi_uart_close(struct tty_struct *tty, struct file * filp)
\r
774 struct spi_uart *uart = tty->driver_data;
\r
775 printk("Enter::%s,LINE=%d,tty->hw_stopped=%d\n",__FUNCTION__,__LINE__,tty->hw_stopped);
\r
779 mutex_lock(&uart->open_lock);
\r
780 BUG_ON(!uart->opened);
\r
783 * This is messy. The tty layer calls us even when open()
\r
784 * returned an error. Ignore this close request if tty->count
\r
785 * is larger than uart->count.
\r
787 if (tty->count > uart->opened) {
\r
788 mutex_unlock(&uart->open_lock);
\r
792 if (--uart->opened == 0) {
\r
793 DBG("Enter::%s,opened=%d\n",__FUNCTION__,uart->opened);
\r
795 spi_uart_shutdown(uart);
\r
796 tty_ldisc_flush(tty);
\r
798 tty->driver_data = NULL;
\r
801 spi_uart_port_put(uart);
\r
802 mutex_unlock(&uart->open_lock);
\r
806 static int spi_uart_write(struct tty_struct * tty, const unsigned char *buf,
\r
809 struct spi_uart *uart = tty->driver_data;
\r
810 struct circ_buf *circ = &uart->xmit;
\r
811 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
816 printk("spi error!!!!\n");
\r
821 DBG("spi_uart_write 1 circ->head=%d,circ->tail=%d\n",circ->head,circ->tail);
\r
823 spin_lock(&uart->write_lock);
\r
825 c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
\r
830 memcpy(circ->buf + circ->head, buf, c);
\r
831 circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
\r
836 spin_unlock(&uart->write_lock);
\r
839 if ( !(uart->ier & UART_IER_THRI)) {
\r
840 //mutex_lock(&port->spi_lock);
\r
841 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
842 /*Note:ICE65L08 output a 'Transmitter holding register interrupt' after 1us*/
\r
844 spi_uart_start_tx(uart);
\r
845 spi_uart_handle_irq(port->spi);
\r
846 //mutex_unlock(&port->spi_lock);
\r
850 //printk("w%d\n",ret);
\r
854 static int spi_uart_write_room(struct tty_struct *tty)
\r
856 struct spi_uart *uart = tty->driver_data;
\r
857 DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);
\r
858 return uart ? circ_chars_free(&uart->xmit) : 0;
\r
861 static int spi_uart_chars_in_buffer(struct tty_struct *tty)
\r
863 struct spi_uart *uart = tty->driver_data;
\r
864 printk("Enter::%s,LINE=%d,circ=%ld****\n",__FUNCTION__,__LINE__,circ_chars_pending(&uart->xmit));
\r
865 return uart ? circ_chars_pending(&uart->xmit) : 0;
\r
868 static void spi_uart_send_xchar(struct tty_struct *tty, char ch)
\r
870 struct spi_uart *uart = tty->driver_data;
\r
871 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
872 printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
874 if (ch && !(uart->ier & UART_IER_THRI)) {
\r
875 //mutex_lock(&port->spi_lock);
\r
876 spi_uart_start_tx(uart);
\r
877 printk("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
878 spi_uart_handle_irq(port->spi);
\r
879 //mutex_unlock(&port->spi_lock);
\r
883 static void spi_uart_throttle(struct tty_struct *tty)
\r
885 struct spi_uart *uart = tty->driver_data;
\r
886 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
887 printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
888 if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))
\r
890 printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
891 //mutex_lock(&port->spi_lock);
\r
892 if (I_IXOFF(tty)) {
\r
893 uart->x_char = STOP_CHAR(tty);
\r
894 spi_uart_start_tx(uart);
\r
895 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
898 if (tty->termios->c_cflag & CRTSCTS)
\r
899 spi_uart_clear_mctrl(uart, TIOCM_RTS);
\r
901 spi_uart_handle_irq(port->spi);
\r
902 //mutex_unlock(&port->spi_lock);
\r
905 static void spi_uart_unthrottle(struct tty_struct *tty)
\r
907 struct spi_uart *uart = tty->driver_data;
\r
908 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
909 printk("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
910 if (!I_IXOFF(tty) && !(tty->termios->c_cflag & CRTSCTS))
\r
912 //mutex_lock(&port->spi_lock);
\r
913 if (I_IXOFF(tty)) {
\r
914 if (uart->x_char) {
\r
917 uart->x_char = START_CHAR(tty);
\r
918 spi_uart_start_tx(uart);
\r
919 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
923 if (tty->termios->c_cflag & CRTSCTS)
\r
924 spi_uart_set_mctrl(uart, TIOCM_RTS);
\r
926 spi_uart_handle_irq(port->spi);
\r
927 //mutex_unlock(&port->spi_lock);
\r
930 static void spi_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
\r
932 struct spi_uart *uart = tty->driver_data;
\r
933 unsigned int cflag = tty->termios->c_cflag;
\r
934 unsigned int mask = TIOCM_DTR;
\r
935 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
937 #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
\r
939 if ((cflag ^ old_termios->c_cflag) == 0 &&
\r
940 RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
\r
943 //mutex_lock(&port->spi_lock);
\r
944 spi_uart_change_speed(uart, tty->termios, old_termios);
\r
946 /* Handle transition to B0 status */
\r
947 if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)){
\r
948 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
949 spi_uart_clear_mctrl(uart, TIOCM_RTS | TIOCM_DTR);
\r
950 //spi_uart_clear_mctrl(uart, TIOCM_RTS);
\r
953 /* Handle transition away from B0 status */
\r
954 if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
\r
955 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
956 if (!(cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags))
\r
958 spi_uart_set_mctrl(uart, mask);
\r
961 /* Handle turning off CRTSCTS */
\r
962 if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
\r
963 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
964 tty->hw_stopped = 0;
\r
965 spi_uart_start_tx(uart);
\r
966 DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);
\r
969 /* Handle turning on CRTSCTS */
\r
970 if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
\r
971 DBG("Enter::%s,LINE=%d,status=0x%x,Handle turning on CRTSCTS*****************\n",__FUNCTION__,__LINE__,spi_uart_get_mctrl(uart));
\r
972 //spi_uart_set_mctrl(uart, TIOCM_RTS);
\r
973 if (!(spi_uart_get_mctrl(uart) & TIOCM_CTS)) {
\r
974 DBG("Enter::%s,LINE=%d,tty->hw_stopped = 1********\n",__FUNCTION__,__LINE__);
\r
975 tty->hw_stopped = 1;
\r
976 spi_uart_stop_tx(uart);
\r
979 //mutex_unlock(&port->spi_lock);
\r
983 static int spi_uart_break_ctl(struct tty_struct *tty, int break_state)
\r
985 struct spi_uart *uart = tty->driver_data;
\r
986 struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);
\r
987 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
988 //mutex_lock(&port->spi_lock);
\r
989 if (break_state == -1)
\r
990 uart->lcr |= UART_LCR_SBC;
\r
992 uart->lcr &= ~UART_LCR_SBC;
\r
993 spi_out(port, UART_LCR, uart->lcr, SEL_UART);
\r
994 //mutex_unlock(&port->spi_lock);
\r
998 static int spi_uart_tiocmget(struct tty_struct *tty, struct file *file)
\r
1000 struct spi_uart *uart = tty->driver_data;
\r
1002 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1003 //mutex_lock(&port->spi_lock);
\r
1004 result = uart->mctrl | spi_uart_get_mctrl(uart);
\r
1005 //mutex_unlock(&port->spi_lock);
\r
1009 static int spi_uart_tiocmset(struct tty_struct *tty, struct file *file,
\r
1010 unsigned int set, unsigned int clear)
\r
1012 struct spi_uart *uart = tty->driver_data;
\r
1013 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1014 //mutex_lock(&port->spi_lock);
\r
1015 spi_uart_update_mctrl(uart, set, clear);
\r
1016 //mutex_unlock(&port->spi_lock);
\r
1022 static int spi_uart_read_proc(char *page, char **start, off_t off,
\r
1023 int count, int *eof, void *data)
\r
1027 DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);
\r
1028 len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n",
\r
1030 for (i = 0; i < UART_NR && len < PAGE_SIZE - 96; i++) {
\r
1031 struct spi_uart *uart = spi_uart_port_get(i);
\r
1033 len += sprintf(page+len, "%d: uart:SPI", i);
\r
1034 if(capable(CAP_SYS_ADMIN)) {
\r
1035 len += sprintf(page + len, " tx:%d rx:%d",
\r
1036 uart->icount.tx, uart->icount.rx);
\r
1037 if (uart->icount.frame)
\r
1038 len += sprintf(page + len, " fe:%d",
\r
1039 uart->icount.frame);
\r
1040 if (uart->icount.parity)
\r
1041 len += sprintf(page + len, " pe:%d",
\r
1042 uart->icount.parity);
\r
1043 if (uart->icount.brk)
\r
1044 len += sprintf(page + len, " brk:%d",
\r
1045 uart->icount.brk);
\r
1046 if (uart->icount.overrun)
\r
1047 len += sprintf(page + len, " oe:%d",
\r
1048 uart->icount.overrun);
\r
1049 if (uart->icount.cts)
\r
1050 len += sprintf(page + len, " cts:%d",
\r
1051 uart->icount.cts);
\r
1052 if (uart->icount.dsr)
\r
1053 len += sprintf(page + len, " dsr:%d",
\r
1054 uart->icount.dsr);
\r
1055 if (uart->icount.rng)
\r
1056 len += sprintf(page + len, " rng:%d",
\r
1057 uart->icount.rng);
\r
1058 if (uart->icount.dcd)
\r
1059 len += sprintf(page + len, " dcd:%d",
\r
1060 uart->icount.dcd);
\r
1062 strcat(page, "\n");
\r
1064 spi_uart_port_put(uart);
\r
1067 if (len + begin > off + count)
\r
1069 if (len + begin < off) {
\r
1077 if (off >= len + begin)
\r
1079 *start = page + (off - begin);
\r
1080 return (count < begin + len - off) ? count : (begin + len - off);
\r
1084 static const struct tty_operations spi_uart_ops = {
\r
1085 .open = spi_uart_open,
\r
1086 .close = spi_uart_close,
\r
1087 .write = spi_uart_write,
\r
1088 .write_room = spi_uart_write_room,
\r
1089 .chars_in_buffer = spi_uart_chars_in_buffer,
\r
1090 .send_xchar = spi_uart_send_xchar,
\r
1091 .throttle = spi_uart_throttle,
\r
1092 .unthrottle = spi_uart_unthrottle,
\r
1093 .set_termios = spi_uart_set_termios,
\r
1094 .break_ctl = spi_uart_break_ctl,
\r
1095 .tiocmget = spi_uart_tiocmget,
\r
1096 .tiocmset = spi_uart_tiocmset,
\r
1097 //.read_proc = spi_uart_read_proc,
\r
1101 static struct tty_driver *spi_uart_tty_driver;
\r
1103 int spi_uart_register(struct spi_fpga_port *port)
\r
1106 struct tty_driver *tty_drv;
\r
1107 spi_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);
\r
1110 tty_drv->owner = THIS_MODULE;
\r
1111 tty_drv->driver_name = "spi_uart";
\r
1112 tty_drv->name = "ttySPI";
\r
1113 tty_drv->major = 0; /* dynamically allocated */
\r
1114 tty_drv->minor_start = 0;
\r
1115 //tty_drv->num = UART_NR;
\r
1116 tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
\r
1117 tty_drv->subtype = SERIAL_TYPE_NORMAL;
\r
1118 tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
\r
1119 tty_drv->init_termios = tty_std_termios;
\r
1120 tty_drv->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
\r
1121 tty_drv->init_termios.c_ispeed = 115200;
\r
1122 tty_drv->init_termios.c_ospeed = 115200;
\r
1123 tty_set_operations(tty_drv, &spi_uart_ops);
\r
1125 ret = tty_register_driver(tty_drv);
\r
1129 //port->uart.uartclk = 64*115200; //MCLK/4
\r
1130 port->uart.uartclk = 60*100000; //MCLK/4
\r
1132 for(i=0; i<UART_NR; i++)
\r
1134 ret = spi_uart_add_port(&port->uart);
\r
1138 struct device *dev;
\r
1139 dev = tty_register_device(spi_uart_tty_driver, port->uart.index, &port->spi->dev);
\r
1140 if (IS_ERR(dev)) {
\r
1141 spi_uart_port_remove(&port->uart);
\r
1142 ret = PTR_ERR(dev);
\r
1150 sprintf(b, "spi_uart_workqueue");
\r
1151 port->uart.spi_uart_workqueue = create_freezeable_workqueue(b);
\r
1152 if (!port->uart.spi_uart_workqueue) {
\r
1153 printk("cannot create workqueue\n");
\r
1156 INIT_WORK(&port->uart.spi_uart_work, spi_uart_work_handler);
\r
1158 setup_timer(&port->uart.uart_timer, spi_testuart_timer, (unsigned long)port);
\r
1159 port->uart.uart_timer.expires = jiffies+2000;
\r
1160 add_timer(&port->uart.uart_timer);
\r
1168 tty_unregister_driver(tty_drv);
\r
1170 put_tty_driver(tty_drv);
\r
1176 int spi_uart_unregister(struct spi_fpga_port *port)
\r
1182 MODULE_DESCRIPTION("Driver for spi2uart.");
\r
1183 MODULE_AUTHOR("luowei <lw@rock-chips.com>");
\r
1184 MODULE_LICENSE("GPL");
\r