Merge remote branch 'common/android-2.6.32' into develop
[firefly-linux-kernel-4.4.55.git] / drivers / fpga / spi_uart.c
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
20 #include <asm/io.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
29 \r
30 #include <mach/spi_fpga.h>\r
31 \r
32 #if defined(CONFIG_SPI_UART_DEBUG)\r
33 #define DBG(x...)   printk(x)\r
34 #else\r
35 #define DBG(x...)\r
36 #endif\r
37 \r
38 #define SPI_UART_TEST 0\r
39 \r
40 #define SPI_UART_FIFO_LEN       32\r
41 #define SPI_UART_TXRX_BUF       0               //send or recieve several bytes one time\r
42 \r
43 static struct tty_driver *spi_uart_tty_driver;\r
44 /*------------------------ÒÔÏÂÊÇspi2uart±äÁ¿-----------------------*/\r
45 \r
46 #define UART_NR         1       /* Number of UARTs this driver can handle */\r
47 \r
48 #define UART_XMIT_SIZE  PAGE_SIZE\r
49 #define WAKEUP_CHARS    1024\r
50 \r
51 #define circ_empty(circ)        ((circ)->head == (circ)->tail)\r
52 #define circ_clear(circ)        ((circ)->head = (circ)->tail = 0)\r
53 \r
54 #define circ_chars_pending(circ) \\r
55                 (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))\r
56 \r
57 #define circ_chars_free(circ) \\r
58                 (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))\r
59 \r
60 \r
61 \r
62 \r
63 static struct spi_uart *spi_uart_table[UART_NR];\r
64 static DEFINE_SPINLOCK(spi_uart_table_lock);\r
65 \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
68 {\r
69         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
70         int index = port->uart.index;\r
71         int reg = 0;\r
72         unsigned char tx_buf[SPI_UART_TXRX_BUF+2];//uart's tx fifo max lenth + 1\r
73         \r
74         reg = ((((reg) | ICE_SEL_UART) & ICE_SEL_WRITE) | ICE_SEL_UART_CH(index));\r
75         tx_buf[0] = reg & 0xff;\r
76         tx_buf[1] = 0;\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
80         return 0;\r
81 }\r
82 \r
83 \r
84 static int spi_uart_read_buf(struct spi_uart *uart, unsigned char *buf, int len)\r
85 {\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
90         \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
97         return stat;\r
98 }\r
99 \r
100 #endif\r
101 \r
102 static int spi_uart_add_port(struct spi_uart *uart)\r
103 {\r
104         int index, ret = -EBUSY;\r
105 \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
110         \r
111         spin_lock(&spi_uart_table_lock);\r
112         for (index = 0; index < UART_NR; index++) \r
113         {\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
118                         ret = 0;\r
119                         break;\r
120                 }\r
121         }\r
122         spin_unlock(&spi_uart_table_lock);\r
123 \r
124         return ret;\r
125 }\r
126 \r
127 static struct spi_uart *spi_uart_port_get(unsigned index)\r
128 {\r
129         struct spi_uart *uart;\r
130 \r
131         if (index >= UART_NR)\r
132                 return NULL;\r
133 \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
138         if (uart)\r
139                 kref_get(&uart->kref);\r
140         spin_unlock(&spi_uart_table_lock);\r
141 \r
142         return uart;\r
143 }\r
144 \r
145 static void spi_uart_port_destroy(struct kref *kref)\r
146 {\r
147         struct spi_uart *uart =\r
148                 container_of(kref, struct spi_uart, kref);\r
149         kfree(uart);\r
150 }\r
151 \r
152 static void spi_uart_port_put(struct spi_uart *uart)\r
153 {\r
154         kref_put(&uart->kref, spi_uart_port_destroy);\r
155 }\r
156 \r
157 static void spi_uart_port_remove(struct spi_uart *uart)\r
158 {\r
159         struct spi_device *spi;\r
160         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
161         \r
162         BUG_ON(spi_uart_table[uart->index] != uart);\r
163 \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
167 \r
168         /*\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
173          */\r
174         mutex_lock(&uart->open_lock);\r
175         //mutex_lock(&port->spi_lock);\r
176         spi = port->spi;\r
177 \r
178         port->spi = NULL;\r
179         //mutex_unlock(&port->spi_lock);\r
180         if (uart->opened)\r
181                 tty_hangup(uart->tty);\r
182         mutex_unlock(&uart->open_lock);\r
183 \r
184         spi_uart_port_put(uart);\r
185 }\r
186 \r
187 static unsigned int spi_uart_get_mctrl(struct spi_uart *uart)\r
188 {\r
189         unsigned char status;\r
190         unsigned int ret;\r
191         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
192         \r
193         status = spi_in(port, UART_MSR, SEL_UART);//\r
194         ret = 0;\r
195 #if 0\r
196         if (status & UART_MSR_DCD)\r
197                 ret |= TIOCM_CAR;\r
198         if (status & UART_MSR_RI)\r
199                 ret |= TIOCM_RNG;\r
200         if (status & UART_MSR_DSR)\r
201                 ret |= TIOCM_DSR;       \r
202         if (status & UART_MSR_CTS)\r
203                 ret |= TIOCM_CTS;\r
204 #endif\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
208         return ret;\r
209 }\r
210 \r
211 static void spi_uart_write_mctrl(struct spi_uart *uart, unsigned int mctrl)\r
212 {\r
213         unsigned char mcr = 0;\r
214         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
215 #if 1\r
216         if (mctrl & TIOCM_RTS)\r
217         {\r
218                 mcr |= UART_MCR_RTS;\r
219                 mcr |= UART_MCR_AFE;\r
220         }\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
229         \r
230 #endif\r
231         \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
234 }\r
235 \r
236 static inline void spi_uart_update_mctrl(struct spi_uart *uart,\r
237                                           unsigned int set, unsigned int clear)\r
238 {\r
239         unsigned int old;\r
240         DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
241         old = uart->mctrl;\r
242         uart->mctrl = (old & ~clear) | set;\r
243         if (old != uart->mctrl)\r
244                 spi_uart_write_mctrl(uart, uart->mctrl);\r
245 }\r
246 \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
249 \r
250 static void spi_uart_change_speed(struct spi_uart *uart,\r
251                                    struct ktermios *termios,\r
252                                    struct ktermios *old)\r
253 {\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
257         \r
258         switch (termios->c_cflag & CSIZE) {\r
259         case CS5:\r
260                 cval = UART_LCR_WLEN5;\r
261                 break;\r
262         case CS6:\r
263                 cval = UART_LCR_WLEN6;\r
264                 break;\r
265         case CS7:\r
266                 cval = UART_LCR_WLEN7;\r
267                 break;\r
268         default:\r
269         case CS8:\r
270                 cval = UART_LCR_WLEN8;\r
271                 break;\r
272         }\r
273 \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
280 \r
281         for (;;) {\r
282                 baud = tty_termios_baud_rate(termios);\r
283                 if (baud == 0)\r
284                         baud = 115200;  /* Special case: B0 rate. */\r
285                 if (baud <= uart->uartclk)\r
286                         break;\r
287                 /*\r
288                  * Oops, the quotient was zero.  Try again with the old\r
289                  * baud rate if possible, otherwise default to 115200.\r
290                  */\r
291                 termios->c_cflag &= ~CBAUD;\r
292                 if (old) {\r
293                         termios->c_cflag |= old->c_cflag & CBAUD;\r
294                         old = NULL;\r
295                 } else\r
296                         termios->c_cflag |= B115200;\r
297         }\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
301         if (baud < 2400)\r
302                 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;\r
303         else\r
304                 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;\r
305 \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
311 \r
312         /*\r
313          * Characters to ignore\r
314          */\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
320                 /*\r
321                  * If we're ignoring parity and break indicators,\r
322                  * ignore overruns too (for real raw support).\r
323                  */\r
324                 if (termios->c_iflag & IGNPAR)\r
325                         uart->ignore_status_mask |= UART_LSR_OE;\r
326         }\r
327 \r
328         /*\r
329          * ignore all characters if CREAD is not set\r
330          */\r
331         if ((termios->c_cflag & CREAD) == 0)\r
332                 uart->ignore_status_mask |= UART_LSR_DR;\r
333 \r
334         /*\r
335          * CTS flow control flag and modem status interrupts\r
336          */\r
337         uart->ier &= ~UART_IER_MSI;\r
338         if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))\r
339         {\r
340                 //uart->ier |= UART_IER_MSI;\r
341                 //uart->mcr = UART_MCR_RTS;//mcr = UART_MCR_RTS while start RTSCTS\r
342         }\r
343 \r
344         uart->lcr = cval;\r
345 \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
355 }\r
356 \r
357 static void spi_uart_start_tx(struct spi_uart *uart)\r
358 {\r
359         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
360 #if 1\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
367                 printk("t,");\r
368         }       \r
369         \r
370         DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
371 #endif\r
372 }\r
373 \r
374 static void spi_uart_stop_tx(struct spi_uart *uart)\r
375 {\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
383                 //printk("p");\r
384         }\r
385         DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
386 }\r
387 \r
388 static void spi_uart_stop_rx(struct spi_uart *uart)\r
389 {\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
394 }\r
395 \r
396 static void spi_uart_receive_chars(struct spi_uart *uart, unsigned int *status)\r
397 {\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
402 \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
406         max_count = 512;\r
407         while (max_count >0 )\r
408         {\r
409                 ret = spi_in(port, UART_RX, SEL_UART);\r
410                 count = (ret >> 8) & 0xff;      \r
411                 if(count == 0)\r
412                 break;\r
413                 buf[0] = ret & 0xff;\r
414                 if(count > 1)\r
415                 {\r
416                         stat = spi_uart_read_buf(uart,buf+1,count-1);\r
417                         if(stat)\r
418                         printk("err:%s:stat=%d,fail to read uart data because of spi bus error!\n",__FUNCTION__,stat);  \r
419                 }\r
420                 max_count -= count;\r
421                 while (count-- >0 )\r
422                 {\r
423                         flag = TTY_NORMAL;\r
424                         ch = buf[num++];\r
425                         tty_insert_flip_char(tty, ch, flag);\r
426                 }\r
427                 \r
428                 tty_flip_buffer_push(tty); \r
429         }\r
430         printk("r%d\n",1024-max_count);\r
431 #else   \r
432         //printk("rx:");\r
433         while (--max_count >0 )\r
434         {\r
435                 ch = spi_in(port, UART_RX, SEL_UART);//\r
436                 //printk("0x%x,",ch&0xff);\r
437                 flag = TTY_NORMAL;\r
438                 uart->icount.rx++;\r
439                 //--max_count;\r
440                 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |\r
441                                         UART_LSR_FE | UART_LSR_OE))) {\r
442                         /*\r
443                          * For statistics only\r
444                          */\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
454 \r
455                         /*\r
456                          * Mask off conditions which should be ignored.\r
457                          */\r
458                         *status &= uart->read_status_mask;\r
459                         if (*status & UART_LSR_BI) {\r
460                                 flag = TTY_BREAK;\r
461                         } else if (*status & UART_LSR_PE)\r
462                                 flag = TTY_PARITY;\r
463                         else if (*status & UART_LSR_FE)\r
464                                 flag = TTY_FRAME;\r
465                 }\r
466 \r
467                 if ((*status & uart->ignore_status_mask & ~UART_LSR_OE) == 0)\r
468                         tty_insert_flip_char(tty, ch, flag);\r
469 \r
470                 /*\r
471                  * Overrun is special.  Since it's reported immediately,\r
472                  * it doesn't affect the current character.\r
473                  */\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
478                         break;\r
479         } \r
480         //printk("\n");\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
484 \r
485 #endif\r
486         \r
487 }\r
488 \r
489 static void spi_uart_transmit_chars(struct spi_uart *uart)\r
490 {\r
491         struct circ_buf *xmit = &uart->xmit;\r
492         int count;\r
493 #if SPI_UART_TXRX_BUF   \r
494         unsigned char buf[SPI_UART_FIFO_LEN];\r
495 #endif\r
496         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
497         \r
498         if (uart->x_char) {\r
499                 spi_out(port, UART_TX, uart->x_char, SEL_UART);\r
500                 uart->icount.tx++;\r
501                 uart->x_char = 0;\r
502                 printk("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
503                 return;\r
504         }\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
509                 return;\r
510         }\r
511         //printk("tx:");\r
512 \r
513 #if SPI_UART_TXRX_BUF\r
514         //send several bytes one time\r
515         count = 0;\r
516         while(count < SPI_UART_FIFO_LEN)\r
517         {\r
518                 buf[count] = xmit->buf[xmit->tail];\r
519                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\r
520                 uart->icount.tx++;\r
521                 count++;\r
522                 if (circ_empty(xmit))\r
523                 break;\r
524         }\r
525         spi_uart_write_buf(uart,buf,count);\r
526 #else\r
527         //send one byte one time\r
528         count = SPI_UART_FIFO_LEN;//\r
529         while(count > 0)\r
530         {\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
534                 uart->icount.tx++;\r
535                 --count;\r
536                 if (circ_empty(xmit))\r
537                 break;  \r
538         }\r
539 #endif\r
540         //printk("\n");\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
543         {       \r
544                 tty_wakeup(uart->tty);\r
545                 printk("k,");\r
546         }\r
547         DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
548         if (circ_empty(xmit))\r
549         {\r
550                 DBG("circ_empty(xmit)\n");\r
551                 spi_uart_stop_tx(uart);\r
552                 printk("e,");\r
553         }\r
554         \r
555         printk("t%d\n",32-count);\r
556 \r
557         DBG("uart->tty->hw_stopped = %d\n",uart->tty->hw_stopped);\r
558 }\r
559 \r
560 #if 0\r
561 static void spi_uart_check_modem_status(struct spi_uart *uart)\r
562 {\r
563         int status;\r
564         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
565         \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
569                 return;\r
570 \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
582                                 if (cts) {\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
587                                 }\r
588                         } else {\r
589                                 if (!cts) {\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
593                                 }\r
594                         }\r
595                 }\r
596         }\r
597         DBG("Enter::%s,LINE=%d,status=0x%x*******\n",__FUNCTION__,__LINE__,status);\r
598 }\r
599 #endif\r
600 \r
601 \r
602 #if SPI_UART_TEST\r
603 #define UART_TEST_LEN 16        //8bit\r
604 unsigned char buf_test_uart[UART_TEST_LEN];\r
605 \r
606 void spi_uart_test_init(struct spi_fpga_port *port)\r
607 {\r
608         unsigned char cval, fcr = 0;\r
609         unsigned int baud, quot;\r
610         unsigned char mcr = 0;\r
611         int ret;\r
612         \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
615         baud = 1500000;\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
621         \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
635 \r
636 \r
637 }\r
638 \r
639 void spi_uart_work_handler(struct work_struct *work)\r
640 {\r
641         int i;\r
642         int count;\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
652 #else\r
653         while(count > 0)\r
654         {\r
655                 spi_out(port, UART_TX, buf_test_uart[UART_TEST_LEN-count], SEL_UART);\r
656                 --count;\r
657         }\r
658 #endif\r
659 \r
660 }\r
661 \r
662 static void spi_testuart_timer(unsigned long data)\r
663 {\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
669 }\r
670 \r
671 #endif\r
672 \r
673 \r
674 \r
675 \r
676 /*\r
677  * This handles the interrupt from one port.\r
678  */\r
679 void spi_uart_handle_irq(struct spi_device *spi)\r
680 {\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
684 \r
685         if (unlikely(uart->in_spi_uart_irq == current))\r
686                 return;\r
687         DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
688 \r
689         /*\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
696          */\r
697          \r
698         uart_iir = spi_in(port, UART_IIR, SEL_UART);//  \r
699         if (uart_iir & UART_IIR_NO_INT)\r
700                 return;\r
701         \r
702         DBG("iir=0x%x\n",uart_iir);\r
703                 \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
707 \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
710         {\r
711                 DBG("Enter::%s,LINE=%d,lsr & UART_LSR_DR************\n",__FUNCTION__,__LINE__);\r
712                 spi_uart_receive_chars(uart, &lsr);     \r
713         }\r
714 \r
715         //spi_uart_check_modem_status(uart);\r
716         \r
717         \r
718         if (lsr & UART_LSR_THRE)\r
719         //if ((uart_iir & UART_IIR_THRI)&&(lsr & UART_LSR_THRE))\r
720         {\r
721                 DBG("Enter::%s,LINE=%d,ICE_STATUS_TXF == 0************\n",__FUNCTION__,__LINE__);\r
722                 spi_uart_transmit_chars(uart);\r
723         }\r
724 \r
725         uart->in_spi_uart_irq = NULL;\r
726 \r
727         DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
728         \r
729 }\r
730 \r
731 static int spi_uart_startup(struct spi_uart *uart)\r
732 {\r
733         unsigned long page;\r
734         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
735         \r
736         DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
737         /*\r
738          * Set the TTY IO error marker - we will only clear this\r
739          * once we have successfully opened the port.\r
740          */\r
741         set_bit(TTY_IO_ERROR, &uart->tty->flags);\r
742 \r
743         /* Initialise and allocate the transmit buffer. */\r
744         page = __get_free_page(GFP_KERNEL);\r
745         if (!page)\r
746                 return -ENOMEM;\r
747 \r
748         uart->xmit.buf = (unsigned char *)page;\r
749         circ_clear(&uart->xmit);\r
750 \r
751         //mutex_lock(&port->spi_lock);\r
752 \r
753         /*\r
754          * Clear the FIFO buffers and disable them.\r
755          * (they will be reenabled in spi_change_speed())\r
756          */\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
761 \r
762         /*\r
763          * Clear the interrupt registers.\r
764          */\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
769 \r
770         /*\r
771          * Now, initialize the UART\r
772          */\r
773         spi_out(port, UART_LCR, UART_LCR_WLEN8, SEL_UART);\r
774 \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
778 \r
779         spi_uart_change_speed(uart, uart->tty->termios, NULL);\r
780 \r
781         if (uart->tty->termios->c_cflag & CBAUD)\r
782                 spi_uart_set_mctrl(uart, TIOCM_RTS | TIOCM_DTR);\r
783 \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
787 \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
793         return 0;\r
794 \r
795 //err1:\r
796         //free_page((unsigned long)uart->xmit.buf);\r
797         //return ret;\r
798 }\r
799 \r
800 static void spi_uart_shutdown(struct spi_uart *uart)\r
801 {\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
806 \r
807         /* TODO: wait here for TX FIFO to drain */\r
808 \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
812 \r
813          /* Disable interrupts from this port */\r
814 \r
815         uart->ier = 0;\r
816         spi_out(port, UART_IER, 0, SEL_UART);\r
817 \r
818         spi_uart_clear_mctrl(uart, TIOCM_OUT2);\r
819 \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
827 \r
828         //mutex_unlock(&port->spi_lock);\r
829 \r
830 //skip:\r
831         /* Free the transmit buffer page. */\r
832         free_page((unsigned long)uart->xmit.buf);\r
833 }\r
834 \r
835 static int spi_uart_open (struct tty_struct *tty, struct file * filp)\r
836 {\r
837         struct spi_uart *uart;\r
838         int ret;\r
839         \r
840         uart = spi_uart_port_get(tty->index);\r
841         if (!uart)\r
842         {\r
843                 DBG("Enter::%s,LINE=%d,!port\n",__FUNCTION__,__LINE__);\r
844                 return -ENODEV;\r
845         }\r
846         DBG("Enter::%s,LINE=%d,tty->index=%d\n",__FUNCTION__,__LINE__,tty->index);\r
847         mutex_lock(&uart->open_lock);\r
848 \r
849         /*\r
850          * Make sure not to mess up with a dead port\r
851          * which has not been closed yet.\r
852          */\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
857                 return -EBUSY;\r
858         }\r
859 \r
860         if (!uart->opened) {\r
861                 tty->driver_data = uart;\r
862                 uart->tty = tty;\r
863                 ret = spi_uart_startup(uart);\r
864                 if (ret) {\r
865                         tty->driver_data = NULL;\r
866                         uart->tty = 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
870                         return ret;\r
871                 }\r
872         }\r
873         uart->opened++;\r
874         DBG("Enter::%s,uart->opened++=%d\n",__FUNCTION__,uart->opened);\r
875         mutex_unlock(&uart->open_lock);\r
876         return 0;\r
877 }\r
878 \r
879 static void spi_uart_close(struct tty_struct *tty, struct file * filp)\r
880 {\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
883         if (!uart)\r
884                 return;\r
885 \r
886         mutex_lock(&uart->open_lock);\r
887         BUG_ON(!uart->opened);\r
888 \r
889         /*\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
893          */\r
894         if (tty->count > uart->opened) {\r
895                 mutex_unlock(&uart->open_lock);\r
896                 return;\r
897         }\r
898 \r
899         if (--uart->opened == 0) {\r
900                 DBG("Enter::%s,opened=%d\n",__FUNCTION__,uart->opened);\r
901                 tty->closing = 1;\r
902                 spi_uart_shutdown(uart);\r
903                 tty_ldisc_flush(tty);\r
904                 uart->tty = NULL;\r
905                 tty->driver_data = NULL;\r
906                 tty->closing = 0;\r
907         }\r
908         spi_uart_port_put(uart);\r
909         mutex_unlock(&uart->open_lock);\r
910 \r
911 }\r
912 \r
913 static int spi_uart_write(struct tty_struct * tty, const unsigned char *buf,\r
914                            int count)\r
915 {\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
919         int c, ret = 0;\r
920 \r
921         if (!port->spi)\r
922         {\r
923                 printk("spi error!!!!\n");\r
924                 return -ENODEV;\r
925         }\r
926 \r
927         \r
928         DBG("spi_uart_write 1 circ->head=%d,circ->tail=%d\n",circ->head,circ->tail);\r
929 \r
930         spin_lock(&uart->write_lock);\r
931         while (1) {\r
932                 c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);\r
933                 if (count < c)\r
934                         c = count;\r
935                 if (c <= 0)\r
936                         break;\r
937                 memcpy(circ->buf + circ->head, buf, c);\r
938                 circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);\r
939                 buf += c;\r
940                 count -= c;\r
941                 ret += c;\r
942         }\r
943         spin_unlock(&uart->write_lock);\r
944         \r
945 #if 1\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
950                         //printk("s,");\r
951                         spi_uart_start_tx(uart);\r
952                         spi_uart_handle_irq(port->spi);\r
953                 //mutex_unlock(&port->spi_lock);        \r
954         }       \r
955 #endif  \r
956 \r
957         //printk("w%d\n",ret);\r
958         return ret;\r
959 }\r
960 \r
961 static int spi_uart_write_room(struct tty_struct *tty)\r
962 {\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
966 }\r
967 \r
968 static int spi_uart_chars_in_buffer(struct tty_struct *tty)\r
969 {\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
973 }\r
974 \r
975 static void spi_uart_send_xchar(struct tty_struct *tty, char ch)\r
976 {\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
980         uart->x_char = ch;\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
987         }\r
988 }\r
989 \r
990 static void spi_uart_throttle(struct tty_struct *tty)\r
991 {\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
996                 return;\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
1003         }\r
1004 \r
1005         if (tty->termios->c_cflag & CRTSCTS)\r
1006                 spi_uart_clear_mctrl(uart, TIOCM_RTS);\r
1007 \r
1008         spi_uart_handle_irq(port->spi);\r
1009         //mutex_unlock(&port->spi_lock);\r
1010 }\r
1011 \r
1012 static void spi_uart_unthrottle(struct tty_struct *tty)\r
1013 {\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
1018                 return;\r
1019         //mutex_lock(&port->spi_lock);\r
1020         if (I_IXOFF(tty)) {\r
1021                 if (uart->x_char) {\r
1022                         uart->x_char = 0;\r
1023                 } else {\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
1027                 }\r
1028         }\r
1029 \r
1030         if (tty->termios->c_cflag & CRTSCTS)\r
1031                 spi_uart_set_mctrl(uart, TIOCM_RTS);\r
1032 \r
1033         spi_uart_handle_irq(port->spi);\r
1034         //mutex_unlock(&port->spi_lock);\r
1035 }\r
1036 \r
1037 static void spi_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)\r
1038 {\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
1043         \r
1044 #define RELEVANT_IFLAG(iflag)   ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))\r
1045 \r
1046         if ((cflag ^ old_termios->c_cflag) == 0 &&\r
1047             RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)\r
1048                 return;\r
1049 \r
1050         //mutex_lock(&port->spi_lock);\r
1051         spi_uart_change_speed(uart, tty->termios, old_termios);\r
1052 \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
1058                 }\r
1059         \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
1066         }\r
1067 \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
1074         }\r
1075 \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
1084                 }\r
1085         }\r
1086         //mutex_unlock(&port->spi_lock);\r
1087 \r
1088 }\r
1089 \r
1090 static int spi_uart_break_ctl(struct tty_struct *tty, int break_state)\r
1091 {\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
1098         else\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
1102         return 0;\r
1103 }\r
1104 \r
1105 static int spi_uart_tiocmget(struct tty_struct *tty, struct file *file)\r
1106 {\r
1107         struct spi_uart *uart = tty->driver_data;\r
1108         int result;\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
1113         return result;\r
1114 }\r
1115 \r
1116 static int spi_uart_tiocmset(struct tty_struct *tty, struct file *file,\r
1117                               unsigned int set, unsigned int clear)\r
1118 {\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
1124 \r
1125         return 0;\r
1126 }\r
1127 \r
1128 #if 0\r
1129 static int spi_uart_read_proc(char *page, char **start, off_t off,\r
1130                                int count, int *eof, void *data)\r
1131 {\r
1132         int i, len = 0;\r
1133         off_t begin = 0;\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
1136                        "", "", "");\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
1139                 if (uart) {\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
1168                         }\r
1169                         strcat(page, "\n");\r
1170                         len++;\r
1171                         spi_uart_port_put(uart);\r
1172                 }\r
1173 \r
1174                 if (len + begin > off + count)\r
1175                         goto done;\r
1176                 if (len + begin < off) {\r
1177                         begin += len;\r
1178                         len = 0;\r
1179                 }\r
1180         }\r
1181         *eof = 1;\r
1182 \r
1183 done:\r
1184         if (off >= len + begin)\r
1185                 return 0;\r
1186         *start = page + (off - begin);\r
1187         return (count < begin + len - off) ? count : (begin + len - off);\r
1188 }\r
1189 #endif\r
1190 \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
1205 };\r
1206 \r
1207 \r
1208 static struct tty_driver *spi_uart_tty_driver;\r
1209 \r
1210 int spi_uart_register(struct spi_fpga_port *port)\r
1211 {\r
1212         int i,ret;\r
1213         struct tty_driver *tty_drv;\r
1214         spi_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);\r
1215         if (!tty_drv)\r
1216                 return -ENOMEM;\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
1231 \r
1232         ret = tty_register_driver(tty_drv);\r
1233         if (ret)\r
1234         goto err1;\r
1235 \r
1236         //port->uart.uartclk = 64*115200;       //MCLK/4\r
1237         port->uart.uartclk = 60*100000; //MCLK/4\r
1238 \r
1239         for(i=0; i<UART_NR; i++)\r
1240         {\r
1241                 ret = spi_uart_add_port(&port->uart);\r
1242                 if (ret) {\r
1243                         goto err2;\r
1244                 } else {\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
1250                                 goto err2;\r
1251                         }\r
1252                 }\r
1253         }\r
1254 \r
1255 #if SPI_UART_TEST\r
1256         char b[20];\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
1261                 return -EBUSY;\r
1262         }\r
1263         INIT_WORK(&port->uart.spi_uart_work, spi_uart_work_handler);\r
1264 \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
1268 \r
1269 #endif\r
1270 \r
1271 \r
1272         return 0;\r
1273 \r
1274 err2:\r
1275         tty_unregister_driver(tty_drv);\r
1276 err1:\r
1277         put_tty_driver(tty_drv);\r
1278         \r
1279         return ret;\r
1280         \r
1281         \r
1282 }\r
1283 int spi_uart_unregister(struct spi_fpga_port *port)\r
1284 {\r
1285 \r
1286         return 0;\r
1287 }\r
1288 \r
1289 MODULE_DESCRIPTION("Driver for spi2uart.");\r
1290 MODULE_AUTHOR("luowei <lw@rock-chips.com>");\r
1291 MODULE_LICENSE("GPL");\r