mirror of
https://github.com/torvalds/linux.git
synced 2026-06-09 07:03:37 +02:00
newton: updata irda serial driver
add ioctl get frame length and start send function
This commit is contained in:
parent
5a270af5a5
commit
cdad3accf2
|
|
@ -21,35 +21,34 @@
|
|||
#include <mach/board.h>
|
||||
#include <linux/irq.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#include "bu92725guw.h"
|
||||
#include "ir_serial.h"
|
||||
|
||||
struct bu92747_port {
|
||||
struct device *dev;
|
||||
struct irda_info *pdata;
|
||||
struct uart_port port;
|
||||
|
||||
int cts; /* last CTS received for flow ctrl */
|
||||
|
||||
/*for FIR fream read*/
|
||||
unsigned long last_frame_length;
|
||||
unsigned long cur_frame_length;
|
||||
wait_queue_head_t data_ready_wq;
|
||||
atomic_t data_ready;
|
||||
|
||||
int tx_empty; /* last TX empty bit */
|
||||
|
||||
spinlock_t conf_lock; /* shared data */
|
||||
int conf_commit; /* need to make changes */
|
||||
int conf; /* configuration for the MAX31000
|
||||
* (bits 0-7, bits 8-11 are irqs) */
|
||||
int rts_commit; /* need to change rts */
|
||||
int rts; /* rts status */
|
||||
int baud; /* current baud rate */
|
||||
|
||||
int parity; /* keeps track if we should send parity */
|
||||
int rx_enabled; /* if we should rx chars */
|
||||
|
||||
int irq; /* irq assigned to the bu92747 */
|
||||
|
||||
int minor; /* minor number */
|
||||
int crystal; /* 1 if 3.6864Mhz crystal 0 for 1.8432 */
|
||||
int loopback; /* 1 if we are in loopback mode */
|
||||
|
||||
/* for handling irqs: need workqueue since we do spi_sync */
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct work;
|
||||
/* set to 1 to make the workhandler exit as soon as possible */
|
||||
|
|
@ -57,10 +56,6 @@ struct bu92747_port {
|
|||
/* need to know we are suspending to avoid deadlock on workqueue */
|
||||
int suspending;
|
||||
|
||||
/* poll time (in ms) for ctrl lines */
|
||||
int poll_time;
|
||||
/* and its timer */
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
||||
#define MAX_BU92747 1
|
||||
|
|
@ -128,12 +123,14 @@ static int bu92747_irda_do_tx(struct bu92747_port *s)
|
|||
}
|
||||
BU92747_IRDA_DBG("\n");
|
||||
|
||||
if (len>0) {
|
||||
s->tx_empty = 0;
|
||||
}
|
||||
|
||||
BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0);
|
||||
s->port.icount.tx += len;
|
||||
xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);
|
||||
|
||||
if (len>0)
|
||||
s->tx_empty = 0;
|
||||
|
||||
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
||||
uart_write_wakeup(&s->port);
|
||||
|
|
@ -151,7 +148,6 @@ static void bu92747_irda_dowork(struct bu92747_port *s)
|
|||
static void bu92747_irda_work(struct work_struct *w)
|
||||
{
|
||||
struct bu92747_port *s = container_of(w, struct bu92747_port, work);
|
||||
u32 irq_src = 0;
|
||||
struct circ_buf *xmit = &s->port.state->xmit;
|
||||
|
||||
dev_dbg(s->dev, "%s\n", __func__);
|
||||
|
|
@ -172,7 +168,8 @@ static void bu92747_irda_work(struct work_struct *w)
|
|||
static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id)
|
||||
{
|
||||
struct bu92747_port *s = dev_id;
|
||||
u32 irq_src = 0;
|
||||
u32 irq_src = 0;
|
||||
unsigned long len;
|
||||
|
||||
dev_dbg(s->dev, "%s\n", __func__);
|
||||
BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);
|
||||
|
|
@ -183,19 +180,30 @@ static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id)
|
|||
| REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {
|
||||
BU92747_IRDA_DBG("[%s][%d]: do err\n", __FUNCTION__, __LINE__);
|
||||
//BU92725GUW_dump_register();
|
||||
//BU92725GUW_clr_fifo();
|
||||
BU92725GUW_clr_fifo();
|
||||
BU92725GUW_reset();
|
||||
if ((BU92725GUW_SEND==irda_hw_get_mode())
|
||||
|| (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {
|
||||
s->tx_empty = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (irq_src & (REG_INT_DRX | FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) {
|
||||
bu92747_irda_do_rx(s);
|
||||
len = bu92747_irda_do_rx(s);
|
||||
if (!IS_FIR(s))
|
||||
tty_flip_buffer_push(s->port.state->port.tty);
|
||||
|
||||
else
|
||||
s->cur_frame_length += len;
|
||||
}
|
||||
|
||||
if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) {
|
||||
tty_flip_buffer_push(s->port.state->port.tty);
|
||||
if (IS_FIR(s)) {
|
||||
s->last_frame_length = s->cur_frame_length;
|
||||
s->cur_frame_length = 0;
|
||||
atomic_set(&(s->data_ready), 1);
|
||||
wake_up(&(s->data_ready_wq) );
|
||||
}
|
||||
}
|
||||
|
||||
if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {
|
||||
|
|
@ -226,6 +234,10 @@ static void bu92747_irda_start_tx(struct uart_port *port)
|
|||
|
||||
dev_dbg(s->dev, "%s\n", __func__);
|
||||
|
||||
//wait for start cmd
|
||||
if (IS_FIR(s))
|
||||
return ;
|
||||
|
||||
if (s->tx_empty)
|
||||
bu92747_irda_do_tx(s);
|
||||
else
|
||||
|
|
@ -256,7 +268,7 @@ static unsigned int bu92747_irda_tx_empty(struct uart_port *port)
|
|||
dev_dbg(s->dev, "%s\n", __func__);
|
||||
|
||||
/* may not be truly up-to-date */
|
||||
bu92747_irda_dowork(s);
|
||||
//bu92747_irda_dowork(s);
|
||||
return s->tx_empty;
|
||||
}
|
||||
|
||||
|
|
@ -331,6 +343,11 @@ static void bu92747_irda_shutdown(struct uart_port *port)
|
|||
destroy_workqueue(s->workqueue);
|
||||
s->workqueue = NULL;
|
||||
}
|
||||
|
||||
atomic_set(&(s->data_ready), 0);
|
||||
s->last_frame_length = 0;
|
||||
s->cur_frame_length = 0;
|
||||
|
||||
if (s->irq)
|
||||
free_irq(s->irq, s);
|
||||
|
||||
|
|
@ -352,6 +369,8 @@ static int bu92747_irda_startup(struct uart_port *port)
|
|||
|
||||
s->baud = 9600;
|
||||
s->rx_enabled = 1;
|
||||
s->last_frame_length = 0;
|
||||
s->cur_frame_length = 0;
|
||||
|
||||
if (s->suspending)
|
||||
return 0;
|
||||
|
|
@ -367,6 +386,8 @@ static int bu92747_irda_startup(struct uart_port *port)
|
|||
}
|
||||
INIT_WORK(&s->work, bu92747_irda_work);
|
||||
|
||||
atomic_set(&(s->data_ready), 0);
|
||||
|
||||
if (request_irq(s->irq, bu92747_irda_irq,
|
||||
IRQ_TYPE_LEVEL_LOW, "bu92747_irda", s) < 0) {
|
||||
dev_warn(s->dev, "cannot allocate irq %d\n", s->irq);
|
||||
|
|
@ -426,7 +447,6 @@ static void bu92747_irda_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|||
struct bu92747_port *s = container_of(port,
|
||||
struct bu92747_port,
|
||||
port);
|
||||
int rts;
|
||||
|
||||
dev_dbg(s->dev, "%s\n", __func__);
|
||||
BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);
|
||||
|
|
@ -472,6 +492,57 @@ bu92747_irda_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
|
||||
}
|
||||
|
||||
static int bu92747_get_frame_length(struct bu92747_port *s)
|
||||
{
|
||||
unsigned long len;
|
||||
wait_event_interruptible_timeout(s->data_ready_wq,
|
||||
atomic_read(&(s->data_ready) ),
|
||||
msecs_to_jiffies(1000) );
|
||||
if ( 0 == atomic_read(&(s->data_ready)) ) {
|
||||
printk("waiting 'data_ready_wq' timed out.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = s->last_frame_length;
|
||||
s->last_frame_length = 0;
|
||||
|
||||
atomic_set(&(s->data_ready), 0);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int bu92747_irda_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct bu92747_port *s = container_of(port,
|
||||
struct bu92747_port,
|
||||
port);
|
||||
void __user *argp = (void __user *)arg;
|
||||
unsigned long len = 0;
|
||||
int ret = 0;
|
||||
BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);
|
||||
|
||||
switch (cmd) {
|
||||
case TTYIR_GETLENGTH:
|
||||
len = bu92747_get_frame_length(s);
|
||||
if (len > 0) {
|
||||
if (copy_to_user(argp, &len, sizeof(len)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
else
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
|
||||
case TTYIR_STARTSEND:
|
||||
bu92747_irda_dowork(s);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct uart_ops bu92747_irda_ops = {
|
||||
.tx_empty = bu92747_irda_tx_empty,
|
||||
.set_mctrl = bu92747_irda_set_mctrl,
|
||||
|
|
@ -489,6 +560,7 @@ static struct uart_ops bu92747_irda_ops = {
|
|||
.request_port = bu92747_irda_request_port,
|
||||
.config_port = bu92747_irda_config_port,
|
||||
.verify_port = bu92747_irda_verify_port,
|
||||
.ioctl = bu92747_irda_ioctl,
|
||||
};
|
||||
|
||||
static struct uart_driver bu92747_irda_uart_driver = {
|
||||
|
|
@ -565,6 +637,8 @@ static int __devinit bu92747_irda_probe(struct platform_device *pdev)
|
|||
/* set shutdown mode to save power. Will be woken-up on open */
|
||||
if (bu92747s[i]->pdata->irda_pwr_ctl)
|
||||
bu92747s[i]->pdata->irda_pwr_ctl(0);
|
||||
|
||||
init_waitqueue_head(&(bu92747s[i]->data_ready_wq));
|
||||
|
||||
mutex_unlock(&bu92747s_lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,4 +3,22 @@
|
|||
|
||||
#include "bu92725guw.h"
|
||||
|
||||
/*
|
||||
* define IOCTL macro
|
||||
*/
|
||||
/* magic number */
|
||||
#define TTYIR_IOC_TYPE 0x56
|
||||
|
||||
/* TTYIR_STARTSEND */
|
||||
/* function: start to send a frame in FIR mode */
|
||||
/* parameter: no parameter */
|
||||
/* return: no return code */
|
||||
#define TTYIR_STARTSEND _IO(TTYIR_IOC_TYPE, 0)
|
||||
|
||||
/* TTYIR_GETLENGTH */
|
||||
/* function: get the length of DATA field in the current frame */
|
||||
/* paramter: no paramter */
|
||||
/* return: the length of DATA field (unit:byte) */
|
||||
#define TTYIR_GETLENGTH _IOR(TTYIR_IOC_TYPE, 1, unsigned long)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user