#include <mach/board.h>\r
#include <linux/irq.h>\r
#include <mach/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
\r
#include "bu92725guw.h"\r
+#include "ir_serial.h"\r
\r
struct bu92747_port {\r
struct device *dev;\r
struct irda_info *pdata;\r
struct uart_port port;\r
- \r
- int cts; /* last CTS received for flow ctrl */\r
+\r
+ /*for FIR fream read*/\r
+ unsigned long last_frame_length;\r
+ unsigned long cur_frame_length; \r
+ wait_queue_head_t data_ready_wq;\r
+ atomic_t data_ready;\r
+\r
int tx_empty; /* last TX empty bit */\r
\r
spinlock_t conf_lock; /* shared data */\r
- int conf_commit; /* need to make changes */\r
- int conf; /* configuration for the MAX31000\r
- * (bits 0-7, bits 8-11 are irqs) */\r
- int rts_commit; /* need to change rts */\r
- int rts; /* rts status */\r
int baud; /* current baud rate */\r
\r
- int parity; /* keeps track if we should send parity */\r
int rx_enabled; /* if we should rx chars */\r
\r
int irq; /* irq assigned to the bu92747 */\r
\r
int minor; /* minor number */\r
- int crystal; /* 1 if 3.6864Mhz crystal 0 for 1.8432 */\r
- int loopback; /* 1 if we are in loopback mode */\r
\r
- /* for handling irqs: need workqueue since we do spi_sync */\r
struct workqueue_struct *workqueue;\r
struct work_struct work;\r
/* set to 1 to make the workhandler exit as soon as possible */\r
/* need to know we are suspending to avoid deadlock on workqueue */\r
int suspending;\r
\r
- /* poll time (in ms) for ctrl lines */\r
- int poll_time;\r
- /* and its timer */\r
- struct timer_list timer;\r
};\r
\r
#define MAX_BU92747 1\r
}\r
BU92747_IRDA_DBG("\n");\r
\r
+ if (len>0) { \r
+ s->tx_empty = 0;\r
+ }\r
+ \r
BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0);\r
s->port.icount.tx += len;\r
xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);\r
\r
- if (len>0) \r
- s->tx_empty = 0;\r
\r
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\r
uart_write_wakeup(&s->port);\r
static void bu92747_irda_work(struct work_struct *w)\r
{\r
struct bu92747_port *s = container_of(w, struct bu92747_port, work);\r
- u32 irq_src = 0; \r
struct circ_buf *xmit = &s->port.state->xmit;\r
\r
dev_dbg(s->dev, "%s\n", __func__);\r
static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id)\r
{\r
struct bu92747_port *s = dev_id;\r
- u32 irq_src = 0; \r
+ u32 irq_src = 0;\r
+ unsigned long len;\r
\r
dev_dbg(s->dev, "%s\n", __func__);\r
BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
| REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {\r
BU92747_IRDA_DBG("[%s][%d]: do err\n", __FUNCTION__, __LINE__);\r
//BU92725GUW_dump_register();\r
- //BU92725GUW_clr_fifo();\r
+ BU92725GUW_clr_fifo();\r
BU92725GUW_reset();\r
+ if ((BU92725GUW_SEND==irda_hw_get_mode())\r
+ || (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {\r
+ s->tx_empty = 1;\r
+ }\r
}\r
\r
if (irq_src & (REG_INT_DRX | FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) {\r
- bu92747_irda_do_rx(s);\r
+ len = bu92747_irda_do_rx(s);\r
if (!IS_FIR(s))\r
tty_flip_buffer_push(s->port.state->port.tty);\r
-\r
+ else\r
+ s->cur_frame_length += len;\r
}\r
\r
if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) {\r
tty_flip_buffer_push(s->port.state->port.tty);\r
+ if (IS_FIR(s)) {\r
+ s->last_frame_length = s->cur_frame_length;\r
+ s->cur_frame_length = 0;\r
+ atomic_set(&(s->data_ready), 1);\r
+ wake_up(&(s->data_ready_wq) );\r
+ }\r
}\r
\r
if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {\r
\r
dev_dbg(s->dev, "%s\n", __func__);\r
\r
+ //wait for start cmd\r
+ if (IS_FIR(s))\r
+ return ;\r
+\r
if (s->tx_empty)\r
bu92747_irda_do_tx(s);\r
else \r
dev_dbg(s->dev, "%s\n", __func__);\r
\r
/* may not be truly up-to-date */\r
- bu92747_irda_dowork(s);\r
+ //bu92747_irda_dowork(s);\r
return s->tx_empty;\r
}\r
\r
destroy_workqueue(s->workqueue);\r
s->workqueue = NULL;\r
}\r
+ \r
+ atomic_set(&(s->data_ready), 0);\r
+ s->last_frame_length = 0;\r
+ s->cur_frame_length = 0;\r
+ \r
if (s->irq)\r
free_irq(s->irq, s);\r
\r
\r
s->baud = 9600;\r
s->rx_enabled = 1;\r
+ s->last_frame_length = 0;\r
+ s->cur_frame_length = 0;\r
\r
if (s->suspending)\r
return 0;\r
}\r
INIT_WORK(&s->work, bu92747_irda_work);\r
\r
+ atomic_set(&(s->data_ready), 0);\r
+\r
if (request_irq(s->irq, bu92747_irda_irq,\r
IRQ_TYPE_LEVEL_LOW, "bu92747_irda", s) < 0) {\r
dev_warn(s->dev, "cannot allocate irq %d\n", s->irq);\r
struct bu92747_port *s = container_of(port,\r
struct bu92747_port,\r
port);\r
- int rts;\r
\r
dev_dbg(s->dev, "%s\n", __func__);\r
BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
\r
}\r
\r
+static int bu92747_get_frame_length(struct bu92747_port *s)\r
+{\r
+ unsigned long len;\r
+ wait_event_interruptible_timeout(s->data_ready_wq, \r
+ atomic_read(&(s->data_ready) ),\r
+ msecs_to_jiffies(1000) );\r
+ if ( 0 == atomic_read(&(s->data_ready)) ) {\r
+ printk("waiting 'data_ready_wq' timed out.");\r
+ return -1;\r
+ }\r
+\r
+ len = s->last_frame_length;\r
+ s->last_frame_length = 0;\r
+ \r
+ atomic_set(&(s->data_ready), 0);\r
+ \r
+ return len;\r
+}\r
+\r
+static int bu92747_irda_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+ void __user *argp = (void __user *)arg;\r
+ unsigned long len = 0;\r
+ int ret = 0;\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+\r
+ switch (cmd) {\r
+ case TTYIR_GETLENGTH:\r
+ len = bu92747_get_frame_length(s);\r
+ if (len > 0) {\r
+ if (copy_to_user(argp, &len, sizeof(len)))\r
+ ret = -EFAULT;\r
+ }\r
+ else\r
+ ret = -EFAULT;\r
+ break;\r
+ \r
+ case TTYIR_STARTSEND: \r
+ bu92747_irda_dowork(s);\r
+ break;\r
+ default:\r
+ ret = -ENOIOCTLCMD;\r
+ break;\r
+ }\r
+ \r
+ return ret;\r
+}\r
+\r
static struct uart_ops bu92747_irda_ops = {\r
.tx_empty = bu92747_irda_tx_empty,\r
.set_mctrl = bu92747_irda_set_mctrl,\r
.request_port = bu92747_irda_request_port,\r
.config_port = bu92747_irda_config_port,\r
.verify_port = bu92747_irda_verify_port,\r
+ .ioctl = bu92747_irda_ioctl,\r
};\r
\r
static struct uart_driver bu92747_irda_uart_driver = {\r
/* set shutdown mode to save power. Will be woken-up on open */\r
if (bu92747s[i]->pdata->irda_pwr_ctl)\r
bu92747s[i]->pdata->irda_pwr_ctl(0);\r
+ \r
+ init_waitqueue_head(&(bu92747s[i]->data_ready_wq));\r
\r
mutex_unlock(&bu92747s_lock);\r
\r