rk fb: from rk3368 fb only need to reserved 1 framebuffer
[firefly-linux-kernel-4.4.55.git] / drivers / net / irda / ir_serial.c
1 /*\r
2  *\r
3  *  Copyright (C) 2011 liuyixing <lyx@rock-chips.com>\r
4  *\r
5  * This program is free software; you can redistribute it and/or modify\r
6  * it under the terms of the GNU General Public License as published by\r
7  * the Free Software Foundation; either version 2 of the License, or\r
8  * (at your option) any later version.\r
9  *\r
10  *\r
11  *note: serial driver for IrDA(SIR and FIR) device\r
12  *\r
13  */\r
14 \r
15 #include <linux/delay.h>\r
16 #include <linux/slab.h>\r
17 #include <linux/device.h>\r
18 #include <linux/serial_core.h>\r
19 #include <linux/serial.h>\r
20 #include <linux/freezer.h>\r
21 #include <mach/board.h>\r
22 #include <linux/irq.h>\r
23 #include <mach/gpio.h>\r
24 #include <asm/uaccess.h>\r
25 #include <asm/atomic.h>\r
26 \r
27 #include "bu92725guw.h"\r
28 #include "ir_serial.h"\r
29 \r
30 \r
31 #define MAX_FRAME_NUM 20\r
32 struct rev_frame_length {\r
33         unsigned long frame_length[MAX_FRAME_NUM];\r
34         int iRead;\r
35         int iWrite;\r
36         int iCount;\r
37 };\r
38 \r
39 #define frame_read_empty(f)               ((f)->iCount == 0)\r
40 #define frame_write_full(f)               ((f)->iCount == MAX_FRAME_NUM)\r
41 #define frame_length_buf_clear(f) ((f)->iCount = (f)->iWrite = (f)->iRead = 0)\r
42 \r
43 struct bu92747_port {\r
44         struct device           *dev;\r
45         struct irda_info *pdata;\r
46         struct uart_port port;\r
47 \r
48         /*for FIR fream read*/\r
49         struct rev_frame_length rev_frames;\r
50         //unsigned long last_frame_length;\r
51         unsigned long cur_frame_length; \r
52         //wait_queue_head_t data_ready_wq;\r
53         //atomic_t data_ready;\r
54         spinlock_t data_lock; \r
55 \r
56         int tx_empty;           /* last TX empty bit */\r
57 \r
58         spinlock_t conf_lock;   /* shared data */\r
59         int baud;               /* current baud rate */\r
60 \r
61         int rx_enabled;         /* if we should rx chars */\r
62 \r
63         int irq_pin;\r
64         int irq;                /* irq assigned to the bu92747 */\r
65 \r
66         int minor;              /* minor number */\r
67 \r
68         struct workqueue_struct *workqueue;\r
69         struct work_struct work;\r
70         /* set to 1 to make the workhandler exit as soon as possible */\r
71         int  force_end_work;\r
72         \r
73         int open_flag;\r
74         /* need to know we are suspending to avoid deadlock on workqueue */\r
75         int suspending;\r
76 \r
77 };\r
78 \r
79 #define MAX_BU92747 1\r
80 #define BU92747_MAJOR 204\r
81 #define BU92747_MINOR 209\r
82 \r
83 static struct bu92747_port *bu92747s[MAX_BU92747]; /* the chips */\r
84 static DEFINE_MUTEX(bu92747s_lock);                /* race on probe */\r
85 #define IS_FIR(s)               ((s)->baud >= 4000000)\r
86 static int max_rate = 4000000; \r
87 static u8 g_receive_buf[BU92725GUW_FIFO_SIZE];\r
88 \r
89 #if 0\r
90 #define IRDA_DBG_FUNC(x...) printk(x)\r
91 #else\r
92 #define IRDA_DBG_FUNC(x...)\r
93 #endif\r
94 \r
95 #if 0\r
96 #define IRDA_DBG_RECV(x...) printk(x)\r
97 #else\r
98 #define IRDA_DBG_RECV(x...)\r
99 #endif\r
100 \r
101 #if 0\r
102 #define IRDA_DBG_SENT(x...) printk(x)\r
103 #else\r
104 #define IRDA_DBG_SENT(x...)\r
105 #endif\r
106 \r
107 /* race on startup&shutdown, mutex lock with CIR driver */\r
108 static DEFINE_MUTEX(irda_cir_lock);\r
109 int bu92747_try_lock(void)\r
110 {\r
111         if (mutex_trylock(&irda_cir_lock))\r
112                 return 1;       //ready\r
113         else\r
114                 return 0;       //busy\r
115 }\r
116 \r
117 void bu92747_unlock(void)\r
118 {\r
119         return mutex_unlock(&irda_cir_lock);\r
120 }\r
121 \r
122 static int add_frame_length(struct rev_frame_length *f, unsigned long length)\r
123 {\r
124         if (frame_write_full(f))\r
125                 return -1;\r
126 \r
127         f->frame_length[f->iWrite] = length;\r
128         f->iCount++;\r
129         f->iWrite = (f->iWrite+1) % MAX_FRAME_NUM;      \r
130         \r
131         return 0;\r
132 }\r
133 \r
134 static int get_frame_length(struct rev_frame_length *f, unsigned long *length)\r
135 {\r
136         if (frame_read_empty(f))\r
137                 return -1;\r
138 \r
139         *length = f->frame_length[f->iRead];\r
140         f->iCount--;\r
141         f->iRead = (f->iRead+1) % MAX_FRAME_NUM;\r
142         \r
143         return 0;\r
144 }\r
145 \r
146 static int bu92747_irda_do_rx(struct bu92747_port *s)\r
147 {\r
148         //int i;\r
149         //unsigned int ch, flag;\r
150         int len;\r
151         struct tty_struct *tty = s->port.state->port.tty;\r
152         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
153 \r
154         if (s->rx_enabled == 0) {\r
155                 BU92725GUW_clr_fifo();\r
156                 BU92725GUW_reset();\r
157                 return 0;\r
158         }\r
159         \r
160         len = BU92725GUW_get_data(g_receive_buf);\r
161         #if 0\r
162         flag = TTY_NORMAL;\r
163         //printk("receive data:\n");\r
164         for (i=0;i<len;i++) {\r
165                 ch = g_receive_buf[i];\r
166                 uart_insert_char(&s->port, 0, 0, ch, flag);\r
167                 s->port.icount.rx++;\r
168                 //printk("%d ", ch);\r
169         }\r
170         //printk("\n");\r
171         #else\r
172         if (len > 0) {\r
173                 IRDA_DBG_RECV("line %d, enter %s, receive %d data........\n", __LINE__, __func__, len);\r
174                 tty_insert_flip_string(tty, g_receive_buf, len);\r
175                 s->port.icount.rx += len;\r
176         }\r
177         #endif\r
178         return len;\r
179  }\r
180 \r
181 static int bu92747_irda_do_tx(struct bu92747_port *s)\r
182 {\r
183         //int i;\r
184         struct circ_buf *xmit = &s->port.state->xmit;\r
185         int len = uart_circ_chars_pending(xmit);\r
186         int len1, len2;\r
187         IRDA_DBG_SENT("line %d, enter %s, sending %d data\n", __LINE__, __FUNCTION__, len);\r
188         \r
189         if (IS_FIR(s)) {\r
190                 irda_hw_tx_enable_irq(BU92725GUW_FIR);\r
191         }\r
192         else {          \r
193                 irda_hw_tx_enable_irq(BU92725GUW_SIR);\r
194         }\r
195         \r
196         if (len>0) {            \r
197                 s->tx_empty = 0;\r
198         }\r
199         \r
200         /* [Modify] AIC 2011/09/27\r
201          * BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0);\r
202          */\r
203         if ( (xmit->tail + len) > UART_XMIT_SIZE ) {\r
204                 len1 = UART_XMIT_SIZE - xmit->tail;\r
205                 len2 = len - len1;\r
206                 BU92725GUW_send_data(xmit->buf+xmit->tail, len1, xmit->buf, len2);\r
207         } else {\r
208                 BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0);\r
209         }\r
210         /* [Modify-end] AIC 2011/09/27 */\r
211         s->port.icount.tx += len;\r
212         xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);\r
213 \r
214         \r
215         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\r
216                 uart_write_wakeup(&s->port);\r
217 \r
218         return len;\r
219 }\r
220 \r
221 static void bu92747_irda_dowork(struct bu92747_port *s)\r
222 {\r
223         if (!s->force_end_work && !work_pending(&s->work) &&\r
224                 !freezing(current) && !s->suspending)\r
225                 queue_work(s->workqueue, &s->work);\r
226 }\r
227 \r
228 static void bu92747_irda_work(struct work_struct *w)\r
229 {\r
230         struct bu92747_port *s = container_of(w, struct bu92747_port, work);\r
231         struct circ_buf *xmit = &s->port.state->xmit;\r
232 \r
233         IRDA_DBG_SENT("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
234 \r
235         if (!s->force_end_work && !freezing(current)) {\r
236                 if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {\r
237                         if (s->tx_empty)\r
238                                 bu92747_irda_do_tx(s);\r
239                         else \r
240                                 bu92747_irda_dowork(s);\r
241                 }\r
242         }\r
243 }\r
244 \r
245 static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id)\r
246 {\r
247         struct bu92747_port *s = dev_id;\r
248         u32 irq_src = 0;\r
249         unsigned long len;\r
250         struct rev_frame_length *f = &(s->rev_frames);\r
251 \r
252         irq_src = irda_hw_get_irqsrc();\r
253         IRDA_DBG_RECV("[%s][%d], 0x%x\n",__FUNCTION__,__LINE__, irq_src);\r
254 \r
255         /* error */\r
256         if (irq_src & (REG_INT_CRC | REG_INT_OE | REG_INT_FE\r
257                 | REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {\r
258                 printk("[%s][%d]: do err, REG_EIR = 0x%x\n", __FUNCTION__, __LINE__, irq_src);\r
259                 BU92725GUW_clr_fifo();\r
260                 BU92725GUW_reset();\r
261                 if ((BU92725GUW_SEND==irda_hw_get_mode())\r
262                         || (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {\r
263                         s->tx_empty = 1;\r
264                 }\r
265         }\r
266         \r
267         if (irq_src & (REG_INT_DRX | FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) {\r
268                 //fixing CA001 (IrSimple mode sending) failing issue\r
269                 /* modified to process a frame ending processing first, when RDE_EI and EOF_EI are happen at the same time.\r
270                  * Before the modification, disconnect packet was processed as the previous packet,\r
271                  * not as a disconnect packet. The packets were combined.\r
272                  */\r
273                 if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) {\r
274                         tty_flip_buffer_push(s->port.state->port.tty);\r
275                         if (IS_FIR(s)) {\r
276                                 spin_lock(&s->data_lock);\r
277                                 if (add_frame_length(f, s->cur_frame_length) == 0) {\r
278                                         s->cur_frame_length = 0;\r
279                                 }\r
280                                 else {\r
281                                         printk("func %s,line %d: FIR frame length buf full......\n", __FUNCTION__, __LINE__);                           \r
282                                 }\r
283                                 spin_unlock(&s->data_lock);\r
284                         }\r
285                 }\r
286                 //~ \r
287 \r
288                 len = bu92747_irda_do_rx(s);\r
289                 if (!IS_FIR(s))\r
290                         tty_flip_buffer_push(s->port.state->port.tty);\r
291                 else {\r
292                         spin_lock(&s->data_lock);\r
293                         s->cur_frame_length += len;\r
294                         spin_unlock(&s->data_lock);\r
295                 }\r
296         }\r
297         \r
298         if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) {\r
299                 spin_lock(&s->data_lock);       // [Modify] AIC 2011/09/30 \r
300                 tty_flip_buffer_push(s->port.state->port.tty);\r
301                 if (IS_FIR(s)) {\r
302                         /* [Modify] AIC 2011/09/30\r
303                          * spin_lock(&s->data_lock);\r
304                          */\r
305                         if (add_frame_length(f, s->cur_frame_length) == 0) {\r
306                                 s->cur_frame_length = 0;\r
307                         }\r
308                         else {\r
309                                 printk("func %s,line %d: FIR frame length buf full......\n", __FUNCTION__, __LINE__);                           \r
310                         }\r
311                         /* [Modify] AIC 2011/09/30 \r
312                          * spin_unlock(&s->data_lock);\r
313                          */\r
314                 }\r
315                 spin_unlock(&s->data_lock);     // [Modify] AIC 2011/09/30\r
316         }\r
317         \r
318         /* [Modify] AIC 2011/09/27\r
319          *\r
320          * if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {\r
321          *      s->tx_empty = 1;\r
322          *      irda_hw_set_moderx();\r
323          * }\r
324          */\r
325         /* [Modify] AIC 2011/09/29\r
326          *    \r
327          * if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {\r
328          *      s->tx_empty = 1;\r
329          *      if ( irq_src & FRM_EVT_TX_TXE ) {\r
330          *              irda_hw_set_moderx();\r
331          *      }\r
332          */\r
333         if ( (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) &&\r
334                                 (BU92725GUW_get_length_in_fifo_buffer() == 0) ) {\r
335                 s->tx_empty = 1;\r
336 \r
337                 if ( irq_src & FRM_EVT_TX_TXE ) {\r
338                         irda_hw_set_moderx();\r
339                 }\r
340         }\r
341         /* [Modify-end] AIC 2011/09/29 */\r
342 #if 0\r
343         /* error */\r
344         if (irq_src & REG_INT_TO) {\r
345                 printk("[%s][%d]: do timeout err\n", __FUNCTION__, __LINE__);\r
346                 BU92725GUW_clr_fifo();\r
347                 BU92725GUW_reset();\r
348                 if ((BU92725GUW_SEND==irda_hw_get_mode())\r
349                         || (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {\r
350                         s->tx_empty = 1;\r
351                 }\r
352         }\r
353 #endif  \r
354         return IRQ_HANDLED;\r
355 }\r
356 \r
357 \r
358 static void bu92747_irda_stop_tx(struct uart_port *port)\r
359 {\r
360         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
361 }\r
362 \r
363 static void bu92747_irda_start_tx(struct uart_port *port)\r
364 {\r
365         struct bu92747_port *s = container_of(port,\r
366                                                   struct bu92747_port,\r
367                                                   port);\r
368         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
369 \r
370         //wait for start cmd\r
371         if (IS_FIR(s))\r
372                 return  ;\r
373 \r
374         bu92747_irda_dowork(s);\r
375 }\r
376 \r
377 static void bu92747_irda_stop_rx(struct uart_port *port)\r
378 {\r
379         struct bu92747_port *s = container_of(port,\r
380                                                   struct bu92747_port,\r
381                                                   port);\r
382 \r
383         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
384 \r
385         s->rx_enabled = 0;\r
386 }\r
387 \r
388 static unsigned int bu92747_irda_tx_empty(struct uart_port *port)\r
389 {\r
390         struct bu92747_port *s = container_of(port,\r
391                                                   struct bu92747_port,\r
392                                                   port);\r
393 \r
394         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
395 \r
396         /* may not be truly up-to-date */\r
397         return s->tx_empty;\r
398 }\r
399 \r
400 static const char *bu92747_irda_type(struct uart_port *port)\r
401 {\r
402         struct bu92747_port *s = container_of(port,\r
403                                                   struct bu92747_port,\r
404                                                   port);\r
405 \r
406         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
407 \r
408         return s->port.type == PORT_IRDA ? "BU92747" : NULL;\r
409 }\r
410 \r
411 static void bu92747_irda_release_port(struct uart_port *port)\r
412 {\r
413         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
414 }\r
415 \r
416 static void bu92747_irda_config_port(struct uart_port *port, int flags)\r
417 {\r
418         struct bu92747_port *s = container_of(port,\r
419                                                   struct bu92747_port,\r
420                                                   port);\r
421 \r
422         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
423 \r
424         if (flags & UART_CONFIG_TYPE)\r
425                 s->port.type = PORT_IRDA;\r
426 }\r
427 \r
428 static int bu92747_irda_verify_port(struct uart_port *port,\r
429                                    struct serial_struct *ser)\r
430 {\r
431         int ret = -EINVAL;\r
432 \r
433         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
434 \r
435         if (ser->type == PORT_UNKNOWN || ser->type == PORT_IRDA)\r
436                 ret = 0;\r
437         \r
438         return ret;\r
439 }\r
440 \r
441 static void bu92747_irda_shutdown(struct uart_port *port)\r
442 {\r
443         struct bu92747_port *s = container_of(port,\r
444                                                   struct bu92747_port,\r
445                                                   port);\r
446         struct rev_frame_length *f = &(s->rev_frames);\r
447 \r
448         printk("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
449 \r
450         if (s->suspending)\r
451                 return;\r
452 \r
453         s->open_flag = 0;\r
454         s->force_end_work = 1;\r
455 \r
456         if (s->workqueue) {\r
457                 flush_workqueue(s->workqueue);\r
458                 destroy_workqueue(s->workqueue);\r
459                 s->workqueue = NULL;\r
460         }\r
461 \r
462         spin_lock(&s->data_lock);\r
463         frame_length_buf_clear(f);\r
464         s->cur_frame_length = 0;\r
465         spin_unlock(&s->data_lock);\r
466                 \r
467         if (s->irq)\r
468                 free_irq(s->irq, s);\r
469         \r
470         irda_hw_shutdown();\r
471         if (s->pdata->irda_pwr_ctl)\r
472                 s->pdata->irda_pwr_ctl(0);      \r
473 \r
474         bu92747_unlock();\r
475 }\r
476 \r
477 static int bu92747_irda_startup(struct uart_port *port)\r
478 {\r
479         struct bu92747_port *s = container_of(port,\r
480                                                   struct bu92747_port,\r
481                                                   port);\r
482         char b[32];\r
483         struct rev_frame_length *f = &(s->rev_frames);\r
484 \r
485         printk("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
486 \r
487         s->rx_enabled = 1;\r
488         \r
489         if (s->suspending)\r
490                 return 0;\r
491 \r
492         if (!bu92747_try_lock()) {\r
493                 printk("func %s, cannot get bu92747 lock, bu92747 in using\n", __func__);\r
494                 return -EBUSY;\r
495         }\r
496         \r
497         s->baud = 9600;\r
498         \r
499         spin_lock(&s->data_lock);\r
500         frame_length_buf_clear(f);\r
501         s->cur_frame_length = 0;\r
502         spin_unlock(&s->data_lock);\r
503 \r
504         s->tx_empty = 1;\r
505         s->force_end_work = 0;\r
506 \r
507         sprintf(b, "bu92747_irda-%d", s->minor);\r
508         s->workqueue = create_rt_workqueue(b);\r
509         if (!s->workqueue) {\r
510                 dev_warn(s->dev, "cannot create workqueue\n");\r
511                 bu92747_unlock();\r
512                 return -EBUSY;\r
513         }\r
514         INIT_WORK(&s->work, bu92747_irda_work);\r
515 \r
516         if (request_irq(s->irq, bu92747_irda_irq,\r
517                         IRQF_TRIGGER_LOW, "bu92747_irda", s) < 0) {\r
518                 dev_warn(s->dev, "cannot allocate irq %d\n", s->irq);\r
519                 s->irq = 0;\r
520                 destroy_workqueue(s->workqueue);\r
521                 s->workqueue = NULL;\r
522                 bu92747_unlock();\r
523                 return -EBUSY;\r
524         }\r
525 \r
526         disable_irq(s->irq);\r
527 \r
528         if (s->pdata->irda_pwr_ctl)\r
529                 s->pdata->irda_pwr_ctl(1);\r
530 \r
531         irda_hw_startup();\r
532         irda_hw_set_moderx();\r
533 \r
534         enable_irq(s->irq);\r
535 \r
536         s->open_flag = 1;\r
537 \r
538         return 0;\r
539 }\r
540 \r
541 static int bu92747_irda_request_port(struct uart_port *port)\r
542 {\r
543         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
544         return 0;\r
545 }\r
546 \r
547 static void bu92747_irda_break_ctl(struct uart_port *port, int break_state)\r
548 {\r
549         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
550 }\r
551 \r
552 static unsigned int bu92747_irda_get_mctrl(struct uart_port *port)\r
553 {\r
554         return  TIOCM_DSR | TIOCM_CAR;\r
555 }\r
556 \r
557 static void bu92747_irda_set_mctrl(struct uart_port *port, unsigned int mctrl)\r
558 {\r
559         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
560 }\r
561 \r
562 static void\r
563 bu92747_irda_set_termios(struct uart_port *port, struct ktermios *termios,\r
564                         struct ktermios *old)\r
565 {\r
566         struct bu92747_port *s = container_of(port,\r
567                                                   struct bu92747_port,\r
568                                                   port);\r
569         int baud = 0;\r
570         unsigned cflag;\r
571         struct tty_struct *tty = s->port.state->port.tty;\r
572 \r
573         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
574         if (!tty)\r
575                 return;\r
576 \r
577         cflag = termios->c_cflag;\r
578         baud = uart_get_baud_rate(port, termios, old, 0, max_rate);\r
579 \r
580         switch (baud) {\r
581         case 9600:\r
582         case 19200:\r
583         case 38400:\r
584         case 57600:\r
585         case 115200:\r
586         case 4000000:\r
587                 if (s->baud!=baud) {\r
588                         IRDA_DBG_RECV("func %s:irda set baudrate %d........\n", __FUNCTION__, baud);\r
589                         irda_hw_set_speed(baud);\r
590                         s->baud = baud;\r
591                         s->tx_empty = 1;\r
592                 }\r
593                 break;\r
594 \r
595         default:\r
596                 break;\r
597         }\r
598         \r
599         uart_update_timeout(port, termios->c_cflag, baud);\r
600 \r
601 }\r
602 \r
603 static int bu92747_get_frame_length(struct bu92747_port *s)\r
604 {\r
605         struct rev_frame_length *f = &(s->rev_frames);\r
606         unsigned long len = 0;\r
607 \r
608         spin_lock(&s->data_lock);\r
609         if (get_frame_length(f, &len) != 0) {\r
610                 IRDA_DBG_RECV("func %s, line %d: FIR data not ready......\n", __FUNCTION__, __LINE__);\r
611                 len = 0;\r
612         }\r
613         spin_unlock(&s->data_lock);\r
614         \r
615         return len;\r
616 }\r
617 \r
618 static int bu92747_irda_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)\r
619 {\r
620         struct bu92747_port *s = container_of(port,\r
621                                                   struct bu92747_port,\r
622                                                   port);\r
623         void __user *argp = (void __user *)arg;\r
624         unsigned long len = 0;\r
625         int ret = 0;\r
626         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
627 \r
628         switch (cmd) {\r
629         case TTYIR_GETLENGTH:\r
630                 len = bu92747_get_frame_length(s);\r
631                 if (len >= 0) {\r
632                         if (copy_to_user(argp, &len, sizeof(len)))\r
633                                 ret = -EFAULT;\r
634                 }\r
635                 else\r
636                         ret = -EFAULT;\r
637                 break;\r
638                 \r
639         case TTYIR_STARTSEND:           \r
640                 bu92747_irda_dowork(s);\r
641                 break;\r
642         default:\r
643                 ret = -ENOIOCTLCMD;\r
644                 break;\r
645         }\r
646         \r
647         return ret;\r
648 }\r
649 \r
650 static struct uart_ops bu92747_irda_ops = {\r
651         .tx_empty       = bu92747_irda_tx_empty,\r
652         .set_mctrl      = bu92747_irda_set_mctrl,\r
653         .get_mctrl      = bu92747_irda_get_mctrl,\r
654         .stop_tx        = bu92747_irda_stop_tx,\r
655         .start_tx       = bu92747_irda_start_tx,\r
656         .stop_rx        = bu92747_irda_stop_rx,\r
657         //.enable_ms      = bu92747_irda_enable_ms,\r
658         .break_ctl      = bu92747_irda_break_ctl,\r
659         .startup        = bu92747_irda_startup,\r
660         .shutdown       = bu92747_irda_shutdown,\r
661         .set_termios    = bu92747_irda_set_termios,\r
662         .type           = bu92747_irda_type,\r
663         .release_port   = bu92747_irda_release_port,\r
664         .request_port   = bu92747_irda_request_port,\r
665         .config_port    = bu92747_irda_config_port,\r
666         .verify_port    = bu92747_irda_verify_port,\r
667         .ioctl                  = bu92747_irda_ioctl,\r
668 };\r
669 \r
670 static struct uart_driver bu92747_irda_uart_driver = {\r
671         .owner          = THIS_MODULE,\r
672         .driver_name    = "ttyIr",\r
673         .dev_name       = "ttyIr",\r
674         .major          = BU92747_MAJOR,\r
675         .minor          = BU92747_MINOR,\r
676         .nr             = MAX_BU92747,\r
677 };\r
678 \r
679 static int uart_driver_registered;\r
680 static int __devinit bu92747_irda_probe(struct platform_device *pdev)\r
681 {\r
682         int i, retval;\r
683     struct irda_info *platdata = pdev->dev.platform_data;\r
684 \r
685         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
686         if (!platdata) {\r
687                 dev_warn(&pdev->dev, "no platform data info\n");\r
688                 return -1;\r
689         }\r
690 \r
691         mutex_lock(&bu92747s_lock);\r
692 \r
693         if (!uart_driver_registered) {\r
694                 uart_driver_registered = 1;\r
695                 retval = uart_register_driver(&bu92747_irda_uart_driver);\r
696                 if (retval) {\r
697                         printk(KERN_ERR "Couldn't register bu92747 uart driver\n");\r
698                         mutex_unlock(&bu92747s_lock);\r
699                         return retval;\r
700                 }\r
701         }\r
702 \r
703         for (i = 0; i < MAX_BU92747; i++)\r
704                 if (!bu92747s[i])\r
705                         break;\r
706         if (i == MAX_BU92747) {\r
707                 dev_warn(&pdev->dev, "too many bu92747 chips\n");\r
708                 mutex_unlock(&bu92747s_lock);\r
709                 return -ENOMEM;\r
710         }\r
711 \r
712         bu92747s[i] = kzalloc(sizeof(struct bu92747_port), GFP_KERNEL);\r
713         if (!bu92747s[i]) {\r
714                 dev_warn(&pdev->dev,\r
715                          "kmalloc for bu92747 structure %d failed!\n", i);\r
716                 mutex_unlock(&bu92747s_lock);\r
717                 return -ENOMEM;\r
718         }\r
719         bu92747s[i]->dev = &pdev->dev;\r
720         bu92747s[i]->irq_pin = platdata->intr_pin;\r
721         bu92747s[i]->irq = gpio_to_irq(platdata->intr_pin);\r
722         if (platdata->iomux_init)\r
723                 platdata->iomux_init();\r
724         bu92747s[i]->pdata = platdata;\r
725         spin_lock_init(&bu92747s[i]->conf_lock);\r
726         dev_set_drvdata(&pdev->dev, bu92747s[i]);\r
727         bu92747s[i]->minor = i;\r
728         dev_dbg(&pdev->dev, "%s: adding port %d\n", __func__, i);\r
729         bu92747s[i]->port.irq = bu92747s[i]->irq;\r
730         bu92747s[i]->port.fifosize = BU92725GUW_FIFO_SIZE;\r
731         bu92747s[i]->port.ops = &bu92747_irda_ops;\r
732         bu92747s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;\r
733         bu92747s[i]->port.line = i;\r
734         bu92747s[i]->port.type = PORT_IRDA;\r
735         bu92747s[i]->port.dev = &pdev->dev;\r
736         retval = uart_add_one_port(&bu92747_irda_uart_driver, &bu92747s[i]->port);\r
737         if (retval < 0)\r
738                 dev_warn(&pdev->dev,\r
739                          "uart_add_one_port failed for line %d with error %d\n",\r
740                          i, retval);\r
741         bu92747s[i]->open_flag = 0;\r
742         bu92747s[i]->suspending = 0;\r
743         /* set shutdown mode to save power. Will be woken-up on open */ \r
744         if (bu92747s[i]->pdata->irda_pwr_ctl)\r
745                 bu92747s[i]->pdata->irda_pwr_ctl(0);\r
746         \r
747         spin_lock_init(&(bu92747s[i]->data_lock));\r
748 \r
749         mutex_unlock(&bu92747s_lock);\r
750         \r
751         return 0;\r
752 }\r
753 \r
754 static int __devexit bu92747_irda_remove(struct platform_device *pdev)\r
755 {\r
756         struct bu92747_port *s = dev_get_drvdata(&pdev->dev);\r
757         int i;\r
758 \r
759         IRDA_DBG_FUNC("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
760         mutex_lock(&bu92747s_lock);\r
761 \r
762         /* find out the index for the chip we are removing */\r
763         for (i = 0; i < MAX_BU92747; i++)\r
764                 if (bu92747s[i] == s)\r
765                         break;\r
766 \r
767         dev_dbg(&pdev->dev, "%s: removing port %d\n", __func__, i);\r
768         uart_remove_one_port(&bu92747_irda_uart_driver, &bu92747s[i]->port);\r
769         kfree(bu92747s[i]);\r
770         bu92747s[i] = NULL;\r
771 \r
772         /* check if this is the last chip we have */\r
773         for (i = 0; i < MAX_BU92747; i++)\r
774                 if (bu92747s[i]) {\r
775                         mutex_unlock(&bu92747s_lock);\r
776                         return 0;\r
777                 }\r
778         pr_debug("removing bu92747 driver\n");\r
779         uart_unregister_driver(&bu92747_irda_uart_driver);\r
780 \r
781         mutex_unlock(&bu92747s_lock);\r
782         return 0;\r
783 }\r
784 \r
785 \r
786 #ifdef CONFIG_PM\r
787 static int bu92747_irda_suspend(struct platform_device *pdev, pm_message_t state)\r
788 {\r
789         struct bu92747_port *s = dev_get_drvdata(&pdev->dev);\r
790 \r
791         if (s->open_flag) {\r
792                 printk("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
793                 disable_irq(s->irq);\r
794                 cancel_work_sync(&s->work);\r
795                 s->suspending = 1;\r
796                 uart_suspend_port(&bu92747_irda_uart_driver, &s->port);\r
797 \r
798                 irda_hw_shutdown();\r
799                 if (s->pdata->irda_pwr_ctl)\r
800                         s->pdata->irda_pwr_ctl(0);\r
801         }\r
802         \r
803         return 0;\r
804 }\r
805 \r
806 static int bu92747_irda_resume(struct platform_device *pdev)\r
807 {\r
808         struct bu92747_port *s = dev_get_drvdata(&pdev->dev);\r
809         \r
810         if (s->open_flag) {\r
811                 printk("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
812                 if (s->pdata->irda_pwr_ctl)\r
813                         s->pdata->irda_pwr_ctl(1);\r
814                 \r
815                 irda_hw_startup();\r
816                 irda_hw_set_speed(s->baud);\r
817                 irda_hw_set_moderx();\r
818 \r
819                 uart_resume_port(&bu92747_irda_uart_driver, &s->port);\r
820                 s->suspending = 0;\r
821 \r
822                 if (!s->tx_empty)\r
823                         s->tx_empty = 1;\r
824                 enable_irq(s->irq);\r
825                 if (s->workqueue && !IS_FIR(s))\r
826                         bu92747_irda_dowork(s);\r
827         }\r
828         \r
829         return 0;\r
830 }\r
831 #else\r
832 #define bu92747_irda_suspend NULL\r
833 #define bu92747_irda_resume  NULL\r
834 #endif\r
835 \r
836 static struct platform_driver bu92747_irda_driver = {\r
837         .driver = {\r
838                 .name = "bu92747_irda",\r
839         .owner  = THIS_MODULE,\r
840         },\r
841         .probe = bu92747_irda_probe,\r
842         .remove = bu92747_irda_remove,\r
843         .suspend = bu92747_irda_suspend,\r
844         .resume = bu92747_irda_resume,\r
845 };\r
846 \r
847 static int __init bu92747_irda_init(void)\r
848 {\r
849         if (platform_driver_register(&bu92747_irda_driver) != 0) {\r
850         printk("Could not register irda driver\n");\r
851         return -EINVAL;\r
852         }\r
853         return 0;\r
854 }\r
855 \r
856 static void __exit bu92747_irda_exit(void)\r
857 {\r
858         platform_driver_unregister(&bu92747_irda_driver);\r
859 }\r
860 \r
861 module_init(bu92747_irda_init);\r
862 module_exit(bu92747_irda_exit);\r
863 MODULE_DESCRIPTION("BU92747 irda driver");\r
864 MODULE_AUTHOR("liuyixing <lyx@rock-chips.com>");\r
865 MODULE_LICENSE("GPL");\r
866 \r