Merge commit 'origin/develop' 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 "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 static struct tty_driver *spi_uart_tty_driver;\r
41 /*------------------------ÒÔÏÂÊÇspi2uart±äÁ¿-----------------------*/\r
42 \r
43 #define UART_NR         1       /* Number of UARTs this driver can handle */\r
44 \r
45 #define UART_XMIT_SIZE  PAGE_SIZE\r
46 #define WAKEUP_CHARS    1024\r
47 \r
48 #define circ_empty(circ)        ((circ)->head == (circ)->tail)\r
49 #define circ_clear(circ)        ((circ)->head = (circ)->tail = 0)\r
50 \r
51 #define circ_chars_pending(circ) \\r
52                 (CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))\r
53 \r
54 #define circ_chars_free(circ) \\r
55                 (CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))\r
56 \r
57 \r
58 \r
59 \r
60 static struct spi_uart *spi_uart_table[UART_NR];\r
61 static DEFINE_SPINLOCK(spi_uart_table_lock);\r
62 \r
63 \r
64 static int spi_uart_add_port(struct spi_uart *uart)\r
65 {\r
66         int index, ret = -EBUSY;\r
67 \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
72         \r
73         spin_lock(&spi_uart_table_lock);\r
74         for (index = 0; index < UART_NR; index++) \r
75         {\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
80                         ret = 0;\r
81                         break;\r
82                 }\r
83         }\r
84         spin_unlock(&spi_uart_table_lock);\r
85 \r
86         return ret;\r
87 }\r
88 \r
89 static struct spi_uart *spi_uart_port_get(unsigned index)\r
90 {\r
91         struct spi_uart *uart;\r
92 \r
93         if (index >= UART_NR)\r
94                 return NULL;\r
95 \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
100         if (uart)\r
101                 kref_get(&uart->kref);\r
102         spin_unlock(&spi_uart_table_lock);\r
103 \r
104         return uart;\r
105 }\r
106 \r
107 static void spi_uart_port_destroy(struct kref *kref)\r
108 {\r
109         struct spi_uart *uart =\r
110                 container_of(kref, struct spi_uart, kref);\r
111         kfree(uart);\r
112 }\r
113 \r
114 static void spi_uart_port_put(struct spi_uart *uart)\r
115 {\r
116         kref_put(&uart->kref, spi_uart_port_destroy);\r
117 }\r
118 \r
119 static void spi_uart_port_remove(struct spi_uart *uart)\r
120 {\r
121         struct spi_device *spi;\r
122         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
123         \r
124         BUG_ON(spi_uart_table[uart->index] != uart);\r
125 \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
129 \r
130         /*\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
135          */\r
136         mutex_lock(&uart->open_lock);\r
137         //mutex_lock(&port->spi_lock);\r
138         spi = port->spi;\r
139 \r
140         port->spi = NULL;\r
141         //mutex_unlock(&port->spi_lock);\r
142         if (uart->opened)\r
143                 tty_hangup(uart->tty);\r
144         mutex_unlock(&uart->open_lock);\r
145 \r
146         spi_uart_port_put(uart);\r
147 }\r
148 \r
149 static unsigned int spi_uart_get_mctrl(struct spi_uart *uart)\r
150 {\r
151         unsigned char status;\r
152         unsigned int ret;\r
153         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
154         \r
155         status = spi_in(port, UART_MSR, SEL_UART);//\r
156         ret = 0;\r
157 #if 0\r
158         if (status & UART_MSR_DCD)\r
159                 ret |= TIOCM_CAR;\r
160         if (status & UART_MSR_RI)\r
161                 ret |= TIOCM_RNG;\r
162         if (status & UART_MSR_DSR)\r
163                 ret |= TIOCM_DSR;       \r
164         if (status & UART_MSR_CTS)\r
165                 ret |= TIOCM_CTS;\r
166 #endif\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
170         return ret;\r
171 }\r
172 \r
173 static void spi_uart_write_mctrl(struct spi_uart *uart, unsigned int mctrl)\r
174 {\r
175         unsigned char mcr = 0;\r
176         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
177 #if 1\r
178         if (mctrl & TIOCM_RTS)\r
179         {\r
180                 mcr |= UART_MCR_RTS;\r
181                 mcr |= UART_MCR_AFE;\r
182         }\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
191         \r
192 #endif\r
193         \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
196 }\r
197 \r
198 static inline void spi_uart_update_mctrl(struct spi_uart *uart,\r
199                                           unsigned int set, unsigned int clear)\r
200 {\r
201         unsigned int old;\r
202         DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
203         old = uart->mctrl;\r
204         uart->mctrl = (old & ~clear) | set;\r
205         if (old != uart->mctrl)\r
206                 spi_uart_write_mctrl(uart, uart->mctrl);\r
207 }\r
208 \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
211 \r
212 static void spi_uart_change_speed(struct spi_uart *uart,\r
213                                    struct ktermios *termios,\r
214                                    struct ktermios *old)\r
215 {\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
219         \r
220         switch (termios->c_cflag & CSIZE) {\r
221         case CS5:\r
222                 cval = UART_LCR_WLEN5;\r
223                 break;\r
224         case CS6:\r
225                 cval = UART_LCR_WLEN6;\r
226                 break;\r
227         case CS7:\r
228                 cval = UART_LCR_WLEN7;\r
229                 break;\r
230         default:\r
231         case CS8:\r
232                 cval = UART_LCR_WLEN8;\r
233                 break;\r
234         }\r
235 \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
242 \r
243         for (;;) {\r
244                 baud = tty_termios_baud_rate(termios);\r
245                 if (baud == 0)\r
246                         baud = 115200;  /* Special case: B0 rate. */\r
247                 if (baud <= uart->uartclk)\r
248                         break;\r
249                 /*\r
250                  * Oops, the quotient was zero.  Try again with the old\r
251                  * baud rate if possible, otherwise default to 115200.\r
252                  */\r
253                 termios->c_cflag &= ~CBAUD;\r
254                 if (old) {\r
255                         termios->c_cflag |= old->c_cflag & CBAUD;\r
256                         old = NULL;\r
257                 } else\r
258                         termios->c_cflag |= B115200;\r
259         }\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
263         if (baud < 2400)\r
264                 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;\r
265         else\r
266                 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;\r
267 \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
273 \r
274         /*\r
275          * Characters to ignore\r
276          */\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
282                 /*\r
283                  * If we're ignoring parity and break indicators,\r
284                  * ignore overruns too (for real raw support).\r
285                  */\r
286                 if (termios->c_iflag & IGNPAR)\r
287                         uart->ignore_status_mask |= UART_LSR_OE;\r
288         }\r
289 \r
290         /*\r
291          * ignore all characters if CREAD is not set\r
292          */\r
293         if ((termios->c_cflag & CREAD) == 0)\r
294                 uart->ignore_status_mask |= UART_LSR_DR;\r
295 \r
296         /*\r
297          * CTS flow control flag and modem status interrupts\r
298          */\r
299         uart->ier &= ~UART_IER_MSI;\r
300         if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))\r
301         {\r
302                 //uart->ier |= UART_IER_MSI;\r
303                 //uart->mcr = UART_MCR_RTS;//mcr = UART_MCR_RTS while start RTSCTS\r
304         }\r
305 \r
306         uart->lcr = cval;\r
307 \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
317 }\r
318 \r
319 static void spi_uart_start_tx(struct spi_uart *uart)\r
320 {\r
321         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
322 #if 1\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
329                 printk("t,");\r
330         }       \r
331         \r
332         DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
333 #endif\r
334 }\r
335 \r
336 static void spi_uart_stop_tx(struct spi_uart *uart)\r
337 {\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
345                 //printk("p");\r
346         }\r
347         DBG("Enter::%s,UART_IER=0x%x\n",__FUNCTION__,uart->ier);\r
348 }\r
349 \r
350 static void spi_uart_stop_rx(struct spi_uart *uart)\r
351 {\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
356 }\r
357 \r
358 static void spi_uart_receive_chars(struct spi_uart *uart, unsigned int *status)\r
359 {\r
360         struct tty_struct *tty = uart->tty;\r
361         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
362         \r
363         unsigned int ch, flag;\r
364         int max_count = 1024;   \r
365         //printk("rx:");\r
366         while (--max_count >0 )\r
367         {\r
368                 ch = spi_in(port, UART_RX, SEL_UART);//\r
369                 //printk("0x%x,",ch&0xff);\r
370                 flag = TTY_NORMAL;\r
371                 uart->icount.rx++;\r
372                 //--max_count;\r
373 #if 1\r
374                 if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |\r
375                                         UART_LSR_FE | UART_LSR_OE))) {\r
376                         /*\r
377                          * For statistics only\r
378                          */\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
388 \r
389                         /*\r
390                          * Mask off conditions which should be ignored.\r
391                          */\r
392                         *status &= uart->read_status_mask;\r
393                         if (*status & UART_LSR_BI) {\r
394                                 flag = TTY_BREAK;\r
395                         } else if (*status & UART_LSR_PE)\r
396                                 flag = TTY_PARITY;\r
397                         else if (*status & UART_LSR_FE)\r
398                                 flag = TTY_FRAME;\r
399                 }\r
400 #endif\r
401                 if ((*status & uart->ignore_status_mask & ~UART_LSR_OE) == 0)\r
402                         tty_insert_flip_char(tty, ch, flag);\r
403 \r
404                 /*\r
405                  * Overrun is special.  Since it's reported immediately,\r
406                  * it doesn't affect the current character.\r
407                  */\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
412                         break;\r
413         } \r
414         //printk("\n");\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
418         \r
419 }\r
420 \r
421 static void spi_uart_transmit_chars(struct spi_uart *uart)\r
422 {\r
423         struct circ_buf *xmit = &uart->xmit;\r
424         int count;\r
425         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
426         \r
427         if (uart->x_char) {\r
428                 spi_out(port, UART_TX, uart->x_char, SEL_UART);\r
429                 uart->icount.tx++;\r
430                 uart->x_char = 0;\r
431                 printk("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
432                 return;\r
433         }\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
438                 return;\r
439         }\r
440         //printk("tx:");\r
441         count = 32;//\r
442         while(count > 0)\r
443         {\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
447                 uart->icount.tx++;\r
448                 --count;\r
449                 if (circ_empty(xmit))\r
450                 break;  \r
451         }\r
452 \r
453         //printk("\n");\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
456         {       \r
457                 tty_wakeup(uart->tty);\r
458                 printk("k,");\r
459         }\r
460         DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
461         if (circ_empty(xmit))\r
462         {\r
463                 DBG("circ_empty(xmit)\n");\r
464                 spi_uart_stop_tx(uart);\r
465                 printk("e,");\r
466         }\r
467         \r
468         printk("t%d\n",32-count);\r
469 \r
470         DBG("uart->tty->hw_stopped = %d\n",uart->tty->hw_stopped);\r
471 }\r
472 \r
473 #if 0\r
474 static void spi_uart_check_modem_status(struct spi_uart *uart)\r
475 {\r
476         int status;\r
477         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
478         \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
482                 return;\r
483 \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
495                                 if (cts) {\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
500                                 }\r
501                         } else {\r
502                                 if (!cts) {\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
506                                 }\r
507                         }\r
508                 }\r
509         }\r
510         DBG("Enter::%s,LINE=%d,status=0x%x*******\n",__FUNCTION__,__LINE__,status);\r
511 }\r
512 #endif\r
513 \r
514 \r
515 #if SPI_UART_TEST\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
519 {\r
520         0x030083,                                       \r
521         0x010000,\r
522         0x000034,                                       // (0100XYH) ÉèÖ÷ÖƵϵÊý£ºXY =  MCLK / (4*²¨ÌØÂÊ)£»\r
523         0x030003,                                       // ÉèÖÃ×Ö½ÚÓÐЧ³¤¶È£º 8 bits£»\r
524         0x01000f,                                       // TX RX ÖжÏ\r
525         0x020080,                                       // ÉèÖô¥·¢µÈ¼¶   ½ÓÊÜFIFOΪ 16bytes ²úÉúÖжϣ»\r
526 };\r
527 \r
528 void spi_uart_work_handler(struct work_struct *work)\r
529 {\r
530         int i;\r
531         int ret,count;\r
532         int offset,value;\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
536 \r
537         for(i=0;i<UART_TEST_LEN;i++)\r
538         buf_test_uart[i] = '0'+i;       \r
539 \r
540         for(i =0; i<sizeof(ice65l08_init_para)/sizeof(ice65l08_init_para[0]); i++)\r
541         {\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
545         }       \r
546         \r
547         count = UART_TEST_LEN;\r
548         while(count > 0)\r
549         {\r
550                 spi_out(port, UART_TX, buf_test_uart[UART_TEST_LEN-count], SEL_UART);\r
551                 --count;\r
552         }\r
553 }\r
554 \r
555 static void spi_testuart_timer(unsigned long data)\r
556 {\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
562 }\r
563 \r
564 #endif\r
565 \r
566 \r
567 \r
568 \r
569 /*\r
570  * This handles the interrupt from one port.\r
571  */\r
572 void spi_uart_handle_irq(struct spi_device *spi)\r
573 {\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
577 \r
578         if (unlikely(uart->in_spi_uart_irq == current))\r
579                 return;\r
580         DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
581 \r
582         /*\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
589          */\r
590          \r
591         uart_iir = spi_in(port, UART_IIR, SEL_UART);//  \r
592         if (uart_iir & UART_IIR_NO_INT)\r
593                 return;\r
594         \r
595         DBG("iir=0x%x\n",uart_iir);\r
596                 \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
600 \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
603         {\r
604                 DBG("Enter::%s,LINE=%d,lsr & UART_LSR_DR************\n",__FUNCTION__,__LINE__);\r
605                 spi_uart_receive_chars(uart, &lsr);     \r
606         }\r
607 \r
608         //spi_uart_check_modem_status(uart);\r
609         \r
610         \r
611         if (lsr & UART_LSR_THRE)\r
612         //if ((uart_iir & UART_IIR_THRI)&&(lsr & UART_LSR_THRE))\r
613         {\r
614                 DBG("Enter::%s,LINE=%d,ICE_STATUS_TXF == 0************\n",__FUNCTION__,__LINE__);\r
615                 spi_uart_transmit_chars(uart);\r
616         }\r
617 \r
618         uart->in_spi_uart_irq = NULL;\r
619 \r
620         DBG("Enter::%s,LINE=%d\n",__FUNCTION__,__LINE__);\r
621         \r
622 }\r
623 \r
624 static int spi_uart_startup(struct spi_uart *uart)\r
625 {\r
626         unsigned long page;\r
627         struct spi_fpga_port *port = container_of(uart, struct spi_fpga_port, uart);\r
628         \r
629         DBG("Enter::%s,LINE=%d************************\n",__FUNCTION__,__LINE__);\r
630         /*\r
631          * Set the TTY IO error marker - we will only clear this\r
632          * once we have successfully opened the port.\r
633          */\r
634         set_bit(TTY_IO_ERROR, &uart->tty->flags);\r
635 \r
636         /* Initialise and allocate the transmit buffer. */\r
637         page = __get_free_page(GFP_KERNEL);\r
638         if (!page)\r
639                 return -ENOMEM;\r
640 \r
641         uart->xmit.buf = (unsigned char *)page;\r
642         circ_clear(&uart->xmit);\r
643 \r
644         //mutex_lock(&port->spi_lock);\r
645 \r
646         /*\r
647          * Clear the FIFO buffers and disable them.\r
648          * (they will be reenabled in spi_change_speed())\r
649          */\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
654 \r
655         /*\r
656          * Clear the interrupt registers.\r
657          */\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
662 \r
663         /*\r
664          * Now, initialize the UART\r
665          */\r
666         spi_out(port, UART_LCR, UART_LCR_WLEN8, SEL_UART);\r
667 \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
671 \r
672         spi_uart_change_speed(uart, uart->tty->termios, NULL);\r
673 \r
674         if (uart->tty->termios->c_cflag & CBAUD)\r
675                 spi_uart_set_mctrl(uart, TIOCM_RTS | TIOCM_DTR);\r
676 \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
680 \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
686         return 0;\r
687 \r
688 //err1:\r
689         //free_page((unsigned long)uart->xmit.buf);\r
690         //return ret;\r
691 }\r
692 \r
693 static void spi_uart_shutdown(struct spi_uart *uart)\r
694 {\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
699 \r
700         /* TODO: wait here for TX FIFO to drain */\r
701 \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
705 \r
706          /* Disable interrupts from this port */\r
707 \r
708         uart->ier = 0;\r
709         spi_out(port, UART_IER, 0, SEL_UART);\r
710 \r
711         spi_uart_clear_mctrl(uart, TIOCM_OUT2);\r
712 \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
720 \r
721         //mutex_unlock(&port->spi_lock);\r
722 \r
723 //skip:\r
724         /* Free the transmit buffer page. */\r
725         free_page((unsigned long)uart->xmit.buf);\r
726 }\r
727 \r
728 static int spi_uart_open (struct tty_struct *tty, struct file * filp)\r
729 {\r
730         struct spi_uart *uart;\r
731         int ret;\r
732         \r
733         uart = spi_uart_port_get(tty->index);\r
734         if (!uart)\r
735         {\r
736                 DBG("Enter::%s,LINE=%d,!port\n",__FUNCTION__,__LINE__);\r
737                 return -ENODEV;\r
738         }\r
739         DBG("Enter::%s,LINE=%d,tty->index=%d\n",__FUNCTION__,__LINE__,tty->index);\r
740         mutex_lock(&uart->open_lock);\r
741 \r
742         /*\r
743          * Make sure not to mess up with a dead port\r
744          * which has not been closed yet.\r
745          */\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
750                 return -EBUSY;\r
751         }\r
752 \r
753         if (!uart->opened) {\r
754                 tty->driver_data = uart;\r
755                 uart->tty = tty;\r
756                 ret = spi_uart_startup(uart);\r
757                 if (ret) {\r
758                         tty->driver_data = NULL;\r
759                         uart->tty = 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
763                         return ret;\r
764                 }\r
765         }\r
766         uart->opened++;\r
767         DBG("Enter::%s,uart->opened++=%d\n",__FUNCTION__,uart->opened);\r
768         mutex_unlock(&uart->open_lock);\r
769         return 0;\r
770 }\r
771 \r
772 static void spi_uart_close(struct tty_struct *tty, struct file * filp)\r
773 {\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
776         if (!uart)\r
777                 return;\r
778 \r
779         mutex_lock(&uart->open_lock);\r
780         BUG_ON(!uart->opened);\r
781 \r
782         /*\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
786          */\r
787         if (tty->count > uart->opened) {\r
788                 mutex_unlock(&uart->open_lock);\r
789                 return;\r
790         }\r
791 \r
792         if (--uart->opened == 0) {\r
793                 DBG("Enter::%s,opened=%d\n",__FUNCTION__,uart->opened);\r
794                 tty->closing = 1;\r
795                 spi_uart_shutdown(uart);\r
796                 tty_ldisc_flush(tty);\r
797                 uart->tty = NULL;\r
798                 tty->driver_data = NULL;\r
799                 tty->closing = 0;\r
800         }\r
801         spi_uart_port_put(uart);\r
802         mutex_unlock(&uart->open_lock);\r
803 \r
804 }\r
805 \r
806 static int spi_uart_write(struct tty_struct * tty, const unsigned char *buf,\r
807                            int count)\r
808 {\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
812         int c, ret = 0;\r
813 \r
814         if (!port->spi)\r
815         {\r
816                 printk("spi error!!!!\n");\r
817                 return -ENODEV;\r
818         }\r
819 \r
820         \r
821         DBG("spi_uart_write 1 circ->head=%d,circ->tail=%d\n",circ->head,circ->tail);\r
822 \r
823         spin_lock(&uart->write_lock);\r
824         while (1) {\r
825                 c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);\r
826                 if (count < c)\r
827                         c = count;\r
828                 if (c <= 0)\r
829                         break;\r
830                 memcpy(circ->buf + circ->head, buf, c);\r
831                 circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);\r
832                 buf += c;\r
833                 count -= c;\r
834                 ret += c;\r
835         }\r
836         spin_unlock(&uart->write_lock);\r
837         \r
838 #if 1\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
843                         //printk("s,");\r
844                         spi_uart_start_tx(uart);\r
845                         spi_uart_handle_irq(port->spi);\r
846                 //mutex_unlock(&port->spi_lock);        \r
847         }       \r
848 #endif  \r
849 \r
850         //printk("w%d\n",ret);\r
851         return ret;\r
852 }\r
853 \r
854 static int spi_uart_write_room(struct tty_struct *tty)\r
855 {\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
859 }\r
860 \r
861 static int spi_uart_chars_in_buffer(struct tty_struct *tty)\r
862 {\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
866 }\r
867 \r
868 static void spi_uart_send_xchar(struct tty_struct *tty, char ch)\r
869 {\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
873         uart->x_char = ch;\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
880         }\r
881 }\r
882 \r
883 static void spi_uart_throttle(struct tty_struct *tty)\r
884 {\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
889                 return;\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
896         }\r
897 \r
898         if (tty->termios->c_cflag & CRTSCTS)\r
899                 spi_uart_clear_mctrl(uart, TIOCM_RTS);\r
900 \r
901         spi_uart_handle_irq(port->spi);\r
902         //mutex_unlock(&port->spi_lock);\r
903 }\r
904 \r
905 static void spi_uart_unthrottle(struct tty_struct *tty)\r
906 {\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
911                 return;\r
912         //mutex_lock(&port->spi_lock);\r
913         if (I_IXOFF(tty)) {\r
914                 if (uart->x_char) {\r
915                         uart->x_char = 0;\r
916                 } else {\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
920                 }\r
921         }\r
922 \r
923         if (tty->termios->c_cflag & CRTSCTS)\r
924                 spi_uart_set_mctrl(uart, TIOCM_RTS);\r
925 \r
926         spi_uart_handle_irq(port->spi);\r
927         //mutex_unlock(&port->spi_lock);\r
928 }\r
929 \r
930 static void spi_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios)\r
931 {\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
936         \r
937 #define RELEVANT_IFLAG(iflag)   ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))\r
938 \r
939         if ((cflag ^ old_termios->c_cflag) == 0 &&\r
940             RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)\r
941                 return;\r
942 \r
943         //mutex_lock(&port->spi_lock);\r
944         spi_uart_change_speed(uart, tty->termios, old_termios);\r
945 \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
951                 }\r
952         \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
957                         mask |= TIOCM_RTS;\r
958                 spi_uart_set_mctrl(uart, mask);\r
959         }\r
960 \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
967         }\r
968 \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
977                 }\r
978         }\r
979         //mutex_unlock(&port->spi_lock);\r
980 \r
981 }\r
982 \r
983 static int spi_uart_break_ctl(struct tty_struct *tty, int break_state)\r
984 {\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
991         else\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
995         return 0;\r
996 }\r
997 \r
998 static int spi_uart_tiocmget(struct tty_struct *tty, struct file *file)\r
999 {\r
1000         struct spi_uart *uart = tty->driver_data;\r
1001         int result;\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
1006         return result;\r
1007 }\r
1008 \r
1009 static int spi_uart_tiocmset(struct tty_struct *tty, struct file *file,\r
1010                               unsigned int set, unsigned int clear)\r
1011 {\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
1017 \r
1018         return 0;\r
1019 }\r
1020 \r
1021 #if 0\r
1022 static int spi_uart_read_proc(char *page, char **start, off_t off,\r
1023                                int count, int *eof, void *data)\r
1024 {\r
1025         int i, len = 0;\r
1026         off_t begin = 0;\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
1029                        "", "", "");\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
1032                 if (uart) {\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
1061                         }\r
1062                         strcat(page, "\n");\r
1063                         len++;\r
1064                         spi_uart_port_put(uart);\r
1065                 }\r
1066 \r
1067                 if (len + begin > off + count)\r
1068                         goto done;\r
1069                 if (len + begin < off) {\r
1070                         begin += len;\r
1071                         len = 0;\r
1072                 }\r
1073         }\r
1074         *eof = 1;\r
1075 \r
1076 done:\r
1077         if (off >= len + begin)\r
1078                 return 0;\r
1079         *start = page + (off - begin);\r
1080         return (count < begin + len - off) ? count : (begin + len - off);\r
1081 }\r
1082 #endif\r
1083 \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
1098 };\r
1099 \r
1100 \r
1101 static struct tty_driver *spi_uart_tty_driver;\r
1102 \r
1103 int spi_uart_register(struct spi_fpga_port *port)\r
1104 {\r
1105         int i,ret;\r
1106         struct tty_driver *tty_drv;\r
1107         spi_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);\r
1108         if (!tty_drv)\r
1109                 return -ENOMEM;\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
1124 \r
1125         ret = tty_register_driver(tty_drv);\r
1126         if (ret)\r
1127         goto err1;\r
1128 \r
1129         //port->uart.uartclk = 64*115200;       //MCLK/4\r
1130         port->uart.uartclk = 60*100000; //MCLK/4\r
1131 \r
1132         for(i=0; i<UART_NR; i++)\r
1133         {\r
1134                 ret = spi_uart_add_port(&port->uart);\r
1135                 if (ret) {\r
1136                         goto err2;\r
1137                 } else {\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
1143                                 goto err2;\r
1144                         }\r
1145                 }\r
1146         }\r
1147 \r
1148 #if SPI_UART_TEST\r
1149         char b[20];\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
1154                 return -EBUSY;\r
1155         }\r
1156         INIT_WORK(&port->uart.spi_uart_work, spi_uart_work_handler);\r
1157 \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
1161 \r
1162 #endif\r
1163 \r
1164 \r
1165         return 0;\r
1166 \r
1167 err2:\r
1168         tty_unregister_driver(tty_drv);\r
1169 err1:\r
1170         put_tty_driver(tty_drv);\r
1171         \r
1172         return ret;\r
1173         \r
1174         \r
1175 }\r
1176 int spi_uart_unregister(struct spi_fpga_port *port)\r
1177 {\r
1178 \r
1179         return 0;\r
1180 }\r
1181 \r
1182 MODULE_DESCRIPTION("Driver for spi2uart.");\r
1183 MODULE_AUTHOR("luowei <lw@rock-chips.com>");\r
1184 MODULE_LICENSE("GPL");\r