wkXXX.c

#include<linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/console.h>
#include <linux/serial_core.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/freezer.h>
#include <linux/spi/spi.h>
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/interrupt.h>

#include <linux/workqueue.h>
#include <linux/platform_device.h>
//#include <mach/map.h>
#include <asm/irq.h>
#include <asm/io.h>
#include "wk2166.h"

/************硬件相关***************/
#include <mach/iomux-mx6q.h>

#define wk2166_irq IMX_GPIO_NR(7,6)// probe里做其他初始化
#define wk2166__cs IMX_GPIO_NR(5,29)//IMX_GPIO_NR(7,2)

MODULE_LICENSE("Dual BSD/GPL");

#define SPI_BUFSIZ      max(32,SMP_CACHE_BYTES)
//#define _DEBUG_WK2XXX
//#define _DEBUG_WK2XXX1
//#define _DEBUG_WK2XXX2
//#define _DEBUG_WK2XXX4
//#define _DEBUG_tla001
//#define _DEBUG_rx

#define CONFIG_DEVFS_FS

#define WK2XXX_PAGE1        1
#define WK2XXX_PAGE0        0

#define WK2XXX_STATUS_PE    1
#define WK2XXX_STATUS_FE    2
#define WK2XXX_STATUS_BRK   4
#define WK2XXX_STATUS_OE    8

static DEFINE_MUTEX(wk2xxxs_lock);                /* race on probe */
static DEFINE_MUTEX(wk2xxs_work_lock);                /* work on probe */
static DEFINE_MUTEX(wk2xxs_spi_lock);                /* spi read & write */

struct wk2xxx_port
{
    //struct timer_list mytimer;    

    struct uart_port port;//[NR_PORTS];
    struct spi_device *spi_wk;
    spinlock_t conf_lock;   /* shared data */
    struct workqueue_struct *workqueue;
    struct work_struct work;
    int suspending;
    void (*wk2xxx_hw_suspend) (int suspend);
    int tx_done;

    int force_end_work;
    int irq;
    int minor;      /* minor number */
    int tx_empty;
    int tx_empty_flag;

    //int start_tx;
    int start_tx_flag;
    int stop_tx_flag;
    int stop_rx_flag;
    int irq_flag;
    int conf_flag;

    int tx_empty_fail;
    int start_tx_fail;
    int stop_tx_fail;
    int stop_rx_fail;
    int irq_fail;
    int conf_fail;
/*
        int work_tx_empty_flag;
        int work_start_tx_flag;
        int work_stop_rx_flag;
        int work_stop_tx_flag;
        int work_irq_flag;
        //int work_irq_fail;
        int work_conf_flag;
*/

    uint8_t new_lcr;
    uint8_t new_scr;
    /*set baud 0f register*/
    uint8_t new_baud1;
    uint8_t new_baud0;
    uint8_t new_pres;

};

static struct wk2xxx_port wk2xxxs[NR_PORTS]; /* the chips */

static int wk2xxx_read_reg(struct spi_device *spi,uint8_t port,uint8_t reg,uint8_t *dat)
{
        struct spi_message msg;
        uint8_t buf_wdat[2];
        uint8_t buf_rdat[2];
        int status;
        mutex_lock(&wk2xxs_spi_lock);

        struct spi_transfer index_xfer = {
                .len            = 2,
                .cs_change      = 1,
        };

        status =0;
		__gpio_set_value(wk2166__cs,0);
        spi_message_init(&msg);
        buf_wdat[0] = 0x40|(((port-1)<<4)|reg);
        buf_wdat[1] = 0x00;
        buf_rdat[0] = 0x00;
        buf_rdat[1] = 0x00;
        index_xfer.tx_buf = buf_wdat;
        index_xfer.rx_buf =(void *) buf_rdat;
        spi_message_add_tail(&index_xfer, &msg);
        status = spi_sync(spi, &msg);
        udelay(5);
        if(status)
	    {
	         return status;
	    }
        *dat = buf_rdat[1];
		__gpio_set_value(wk2166__cs,1);
		mutex_unlock(&wk2xxs_spi_lock);
    return 0;

}

static int wk2xxx_write_reg(struct spi_device *spi,uint8_t port,uint8_t reg,uint8_t dat)
{
        struct spi_message msg;
        uint8_t buf_reg[2];
        int status;
		mutex_lock(&wk2xxs_spi_lock);
        struct spi_transfer index_xfer = {
                .len            = 2,
                .cs_change      = 1,
        };
		__gpio_set_value(wk2166__cs,0);
        spi_message_init(&msg);
        /* register index */
        buf_reg[0] = ((port-1)<<4)|reg;
        buf_reg[1] = dat;
        index_xfer.tx_buf = buf_reg;
        spi_message_add_tail(&index_xfer, &msg);
        status = spi_sync(spi, &msg);
    	udelay(5);
        if(status)
        {
    		 return status;
   		}
		__gpio_set_value(wk2166__cs,1);
		mutex_unlock(&wk2xxs_spi_lock);
        return status;
}

static void wk2xxxirq_app(struct uart_port *port);//
static void conf_wk2xxx_subport(struct uart_port *port);//
static void wk2xxx_work(struct work_struct *w);
static void wk2xxx_stop_tx(struct uart_port *port);//
static u_int wk2xxx_tx_empty(struct uart_port *port);// or query the tx fifo is not empty?

static int wk2xxx_dowork(struct wk2xxx_port *s)
{
#ifdef _DEBUG_WK2XXX
    printk("--wk2xxx_dowork---in---\n");
#endif

    if (!s->force_end_work && !work_pending(&s->work) && !freezing(current) && !s->suspending)
    {
        queue_work(s->workqueue, &s->work);//
        #ifdef _DEBUG_WK2XXX
        printk("--queue_work---ok---\n");
         printk("--wk2xxx_dowork---exit---\n");
// printk("work_pending =: %d s->force_end_work  = : %d freezing(current) = :%d s->suspending= :%d\n" ,work_pending(&s->work),s->force_end_work ,freezing(current),s->suspending);
      #endif
        return 1;
    }
    else
    {
      #ifdef _DEBUG_WK2XXX
        printk("--queue_work---error---\n");
         printk("--wk2xxx_dowork---exit---\n");
      #endif

//printk("work_pending =: %d s->force_end_work  = : %d freezing(current) = :%d s->suspending= :%d\n" ,work_pending(&s->work),s->force_end_work ,freezing(current),s->suspending);
    //  return 0;
//  printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s->irq_flag,s->tx_empty);
        return 0;
    }

}

static void wk2xxx_work(struct work_struct *w)
{
#ifdef _DEBUG_WK2XXX
    printk("--wk2xxx_work---in---\n");
#endif

    struct wk2xxx_port *s = container_of(w, struct wk2xxx_port, work);
    uint8_t rx;

    int work_tx_empty_flag;
    int work_start_tx_flag; 

    int work_stop_rx_flag;
    int work_stop_tx_flag;

    int work_irq_flag;
    //int work_irq_fail;
    int work_conf_flag;
    do {

            mutex_lock(&wk2xxs_work_lock);
            //spin_lock(&s->conf_lock);
        /*work_tx_empty_flag = s->tx_empty_flag;
        if(work_tx_empty_flag)
        s->tx_empty_flag = 0;*/
            work_start_tx_flag = s->start_tx_flag;
        if(work_start_tx_flag)
        s->start_tx_flag = 0;
        /*work_stop_tx_flag = s->stop_tx_flag;
        if(work_stop_tx_flag)
        s->stop_tx_flag = 0;*/
        work_stop_rx_flag = s->stop_rx_flag;
        if(work_stop_rx_flag)
        s->stop_rx_flag = 0;
        work_conf_flag = s->conf_flag;
        if(work_conf_flag)
        s->conf_flag = 0;

        work_irq_flag = s->irq_flag;
        if(work_irq_flag)
        s->irq_flag = 0;

        //work_irq_fail = s->irq_fail;
        //if(work_irq_fail)
        //s->irq_fail = 0;

        //spin_unlock(&s->conf_lock);
        mutex_unlock(&wk2xxs_work_lock);

        if(work_conf_flag)
        {
        conf_wk2xxx_subport(&s->port);
        }
        /*if(work_tx_empty_flag)
        {

        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,&rx);
        s->tx_empty = (rx & WK2XXX_TDAT)<=0;
#ifdef _DEBUG_WK2XXX1
            printk(KERN_ALERT "s->tx_empty_fail----FSR:%d--s->tx_empty:%d--\n",rx,s->tx_empty);
 #endif

        }*/
        if(work_start_tx_flag)
        {
         wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
         rx |= WK2XXX_TFTRIG_IEN;
         wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
        }
      /* if(work_stop_tx_flag)
        {
        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
            rx &=~WK2XXX_TFTRIG_IEN;
            wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
            rx &= ~WK2XXX_TFTRIG_INT;
            wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
        }*/
        if(work_stop_rx_flag)
        {
            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
         #ifdef _DEBUG_WK2XXX1
              printk(KERN_ALERT "stop_rx_flag----SIER:%d--\n",rx);
           #endif

        rx &=~WK2XXX_RFTRIG_IEN;
        rx &=~WK2XXX_RXOUT_IEN;
            wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
         #ifdef _DEBUG_WK2XXX1
               printk(KERN_ALERT "stop_rx_flag----SIFR:%d--\n",rx);
          #endif

            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);

            rx &= ~WK2XXX_RFTRIG_INT;
            rx &= ~WK2XXX_RXOVT_INT;
            wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
        #ifdef _DEBUG_WK2XXX1
             printk(KERN_ALERT "stop_rx_flag----SIFR:%d--\n",rx);
   #endif

        }

        if(work_irq_flag)
        {
            wk2xxxirq_app(&s->port);
            s->irq_fail = 1;
        }

        }while (!s->force_end_work && !freezing(current) && \
        (work_irq_flag || work_stop_rx_flag || \
         work_stop_tx_flag || work_tx_empty_flag || work_conf_flag));
/*
    }while (!s->force_end_work && !freezing(current) && \
        ((s->work_irq_flag != s->irq_flag) ||\
         (s->work_stop_rx_flag != s->stop_rx_flag) ||\
         (s->work_stop_tx_flag != s->stop_tx_flag) ||\
         (s->work_tx_empty_flag != s->tx_empty_flag) ||\
         (s->work_conf_flag != s->conf_flag)));

*/

#ifdef _DEBUG_WK2XXX
        printk("-----exit------- work ------\n");
#endif

        if(s->conf_fail)
        {
        conf_wk2xxx_subport(&s->port);
        s->conf_fail =0;
        }

        /*if(s->tx_empty_fail)
        {
            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,&rx);

            s->tx_empty = (rx & WK2XXX_TDAT) == 0;
        s->tx_empty_fail =0;
 #ifdef _DEBUG_WK2XXX1
            printk(KERN_ALERT "s->tx_empty_fail----FSR:%d--s->tx_empty:%d--s->tx_empty_fail :%d--\n",rx,s->tx_empty,s->tx_empty_fail );
 #endif

        }*/

        if(s->start_tx_fail)
        {
            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
            rx |= WK2XXX_TFTRIG_IEN;
            wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
        s->start_tx_fail =0;
        }

       /* if(s->stop_tx_fail)
        {

        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
        rx &=~WK2XXX_TFTRIG_IEN;
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
                rx &= ~WK2XXX_TFTRIG_INT;
                wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
        s->stop_tx_fail =0;

        }*/

       if(s->stop_rx_fail)
        {
            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
            rx &=~WK2XXX_RFTRIG_IEN;
            rx &=~WK2XXX_RXOUT_IEN;
            wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);

            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
            rx &= ~WK2XXX_RFTRIG_INT;
            rx &= ~WK2XXX_RXOVT_INT;
            wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
            s->stop_rx_fail =0;
        }
        if(s->irq_fail)
        {
            s->irq_fail = 0;
            enable_irq(s->port.irq);
             //s->irq_fail = 0;
        }
//printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s->          irq_flag,s->tx_empty);

#ifdef _DEBUG_WK2XXX
    printk("--wk2xxx_work---exit---\n");
#endif
//mutex_unlock(&wk2xxs_work_lock);
}

static void wk2xxx_rx_chars(struct uart_port *port)//vk32xx_port *port)
{
#ifdef _DEBUG_rx
      printk(KERN_ALERT "wk2xxx_rx_chars()---------in---\n");
#endif

    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
    uint8_t fsr,lsr,dat[1];
    unsigned int ch, flg, ignored=0,status = 0,rx_count=0;
#ifdef _DEBUG_tla001
	int i;
	for(i=1;i<5;i++)
		{
			wk2xxx_write_reg(s->spi_wk,i,WK2XXX_SPAGE,WK2XXX_PAGE0);
			wk2xxx_read_reg(s->spi_wk,i,WK2XXX_GENA,dat);
		    printk(KERN_ALERT "Port%d WK2XXX_GENA****0x%x\n",i,dat[0]);
			wk2xxx_read_reg(s->spi_wk,i,WK2XXX_SIER,dat);
		    printk(KERN_ALERT "Port%d WK2XXX_SIER****0x%x\n",i,dat[0]);
			wk2xxx_read_reg(s->spi_wk,i,WK2XXX_SIFR,dat);
		    printk(KERN_ALERT "Port%d WK2XXX_SIFR****0x%x\n",i,dat[0]);
			wk2xxx_write_reg(s->spi_wk,i,WK2XXX_SPAGE,WK2XXX_PAGE1);
			wk2xxx_read_reg(s->spi_wk,i,WK2XXX_BAUD1,dat);
		    printk(KERN_ALERT "Port%d WK2XXX_BAUD1****0x%x\n",i,dat[0]);
			wk2xxx_read_reg(s->spi_wk,i,WK2XXX_BAUD0,dat);
		    printk(KERN_ALERT "Port%d WK2XXX_BAUD0****0x%x\n",i,dat[0]);
			wk2xxx_read_reg(s->spi_wk,i,WK2XXX_RFTL,dat);
		    printk(KERN_ALERT "Port%d WK2XXX_RFTL****0x%x\n",i,dat[0]);
			wk2xxx_read_reg(s->spi_wk,i,WK2XXX_TFTL,dat);
		    printk(KERN_ALERT "Port%d WK2XXX_TFTL****0x%x\n\n",i,dat[0]);
	}

#endif
	wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0

	wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
    fsr = dat[0];
    wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_LSR,dat);
    lsr = dat[0];
#ifdef _DEBUG_WK2XXX1
      printk(KERN_ALERT "wk2xxx_rx_chars()----port:%d--fsr:%d--lsr:%d--\n",s->port.iobase,fsr,lsr);
#endif

    while (fsr& WK2XXX_RDAT)/**/
        {
            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,dat);
        ch = (int)dat[0];
#ifdef _DEBUG_WK2XXX4 

        printk(KERN_ALERT "wk2xxx_rx_chars()----port:%d--RXDAT:0x%x----\n",s->port.iobase,ch);
#endif

        s->port.icount.rx++;
        //rx_count++;
#ifdef _DEBUG_WK2XXX1
            printk(KERN_ALERT "icount.rx:%d\n",s->port.icount.rx);
#endif
            flg = TTY_NORMAL;
        if (lsr&(WK2XXX_OE |WK2XXX_FE|WK2XXX_PE|WK2XXX_BI))
                {
               printk(KERN_ALERT "all err\n");
                        //goto handle_error;
            if (lsr & WK2XXX_PE)
                {
                        s->port.icount.parity++;
                        status |= WK2XXX_STATUS_PE;
                        flg = TTY_PARITY;
                }
                if (lsr & WK2XXX_FE)
                {
                        s->port.icount.frame++;
                        status |= WK2XXX_STATUS_FE;
                        flg = TTY_FRAME;
                }
                if (lsr & WK2XXX_OE)
                {
                        s->port.icount.overrun++;
                        status |= WK2XXX_STATUS_OE;
                        flg = TTY_OVERRUN;
                }
                if(lsr&fsr & WK2XXX_BI)
                {
                        s->port.icount.brk++;
                        status |= WK2XXX_STATUS_BRK;
                        flg = TTY_BREAK;
                }

                if (++ignored > 100)
                       goto out;

                 goto ignore_char;
        }

error_return:
    if (uart_handle_sysrq_char(&s->port,ch))//.state, ch))
        goto ignore_char;

        uart_insert_char(&s->port, status, WK2XXX_STATUS_OE, ch, flg);
        rx_count++;

        if ((rx_count >= 8 ) && (s->port.state->port.tty != NULL))
        {
         tty_flip_buffer_push(s->port.state->port.tty);
         rx_count = 0;
        }
#ifdef _DEBUG_WK2XXX1
                printk(KERN_ALERT  " s->port.icount.rx = 0x%X char = 0x%X flg = 0x%X port = %d rx_count = %d\n",s->port.icount.rx,ch,flg,s->port.iobase,rx_count);
#endif
        ignore_char:

            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
            fsr = dat[0];
            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_LSR,dat);
            lsr = dat[0];
        }
out:
if((rx_count > 0)&&(s->port.state->port.tty != NULL))
{
#ifdef _DEBUG_WK2XXX1
        printk(KERN_ALERT  "push buffer tty flip port = :%d count = :%d\n",s->port.iobase,rx_count);
#endif
        tty_flip_buffer_push(s->port.state->port.tty);
}

#ifdef _DEBUG_WK2XXX1
                 printk(KERN_ALERT "wk2xxx_rx_chars()---------out---\n");
#endif

      return;
#ifdef SUPPORT_SYSRQ
        s->port.state->sysrq = 0;
#endif
        goto error_return;

#ifdef _DEBUG_rx
    printk("--wk2xxx_rx_chars---exit---\n");
#endif

}

static void wk2xxx_tx_chars(struct uart_port *port)//
{
#ifdef _DEBUG_WK2XXX4
    printk("--wk2xxx_tx_chars---in---\n");
#endif

    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
    uint8_t fsr,dat[1];
    int count;
#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "                             in  wk2xxx_tx_chars()\n");
#endif
        if (s->port.x_char)
        {
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,s->port.x_char);
                s->port.icount.tx++;
                s->port.x_char = 0;
                goto out;
        //return;
        }

        if(uart_circ_empty(&s->port.state->xmit) || uart_tx_stopped(&s->port))
               {
        //wk2xxx_stop_tx(&s->port);
        goto out;
                //return;
               }

    /*
     * Tried using FIFO (not checking TNF) for fifo fill:
     * still had the '1 bytes repeated' problem.
    */
    wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
    fsr = dat[0];

#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "fsr:%x\n",fsr);
#endif
    //count = s->port.fifosize / 2;
    count = s->port.fifosize;
    //count = 64;
    do
    {

        if((fsr & WK2XXX_TFULL)|uart_circ_empty(&s->port.state->xmit))
            goto out;
         // break;
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,s->port.state->xmit.buf[s->port.state->xmit.tail]);
#ifdef _DEBUG_WK2XXX
 printk(KERN_ALERT "wk2xxx_tx_chars()----port:%d--TXDAT:0x%x----\n",s->port.iobase,s->port.state->xmit.buf[s->port.state->xmit.tail]);
 #endif
//udelay(1000);
 s->port.state->xmit.tail = (s->port.state->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
        s->port.icount.tx++;
#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "xmit.head:%d,xmit.tail:%d,char:%d,fsr:0x%X,port = %d\n",s->port.state->xmit.head,s->port.state->xmit.tail,s->port.state->xmit.buf[s->port.state->xmit.tail],fsr,s->port.iobase);
#endif
        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
        fsr = dat[0];
    }while(--count>0);
 #ifdef _DEBUG_WK2XXX
    do
    {
        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
        fsr = dat[0];
    }while(fsr&WK2XXX_TDAT>0);
    printk(KERN_ALERT "tx_char --fsr:0x%X,port = %d\n",fsr,s->port.iobase);
  #endif
    out:wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
          fsr = dat[0];
    //printk(KERN_ALERT "tx_char --fsr:0x%X,port = %d\n",fsr,s->port.iobase);
            if((fsr&WK2XXX_TDAT)==0)
        {
        //printk(KERN_ALERT "tx_char1 --fsr:0x%X,port = %d\n",fsr,s->port.iobase);
        if (uart_circ_chars_pending(&s->port.state->xmit) < WAKEUP_CHARS)
            uart_write_wakeup(&s->port); 

        if (uart_circ_empty(&s->port.state->xmit))
        {
            wk2xxx_stop_tx(&s->port);
        }
        }
#ifdef _DEBUG_WK2XXX
    printk("--wk2xxx_tx_chars---exit---\n");
#endif

}

static irqreturn_t wk2xxx_irq(int irq, void *dev_id)//
{
#ifdef _DEBUG_WK2XXX
    printk("--wk2xxx_irq---in---\n");
#endif

    struct wk2xxx_port *s = dev_id;
    //char sier;
    disable_irq_nosync(s->port.irq);
        //s->irq_fail=1;
        //s->irq_flag = 1;
    //mutex_unlock(&vk32xxs_work_lock);
    //vk32xx_dowork(s);

    if(wk2xxx_dowork(s))
    {
    //disable_irq_nosync(s->port.irq);
    //if(!s->irq_fail)
    //{
        s->irq_flag = 1;
			#ifdef _DEBUG_tla00
    				printk(KERN_ALERT "****** irq_flag=1*****\n");
			#endif
        //s->irq_fail = 0;
    //}
    }
    else
    {
        //if(!s->irq_flag)
        s->irq_fail = 1;
		#ifdef _DEBUG_tla001
    				printk(KERN_ALERT "****** irq_fail=1*****\n");
		#endif
    }
    //disable_irq_nosysc(s->port.irq);
#ifdef _DEBUG_WK2XXX
    printk("--wk2xxx_irq---exit---\n");
#endif

    return IRQ_HANDLED;
}

static void wk2xxxirq_app(struct uart_port *port)//
{

        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
#ifdef _DEBUG_WK2XXX1
    printk(KERN_ALERT "wk2xxxirq_app()------port:%d--------------\n",s->port.iobase);
#endif
        unsigned int  pass_counter = 0;
        uint8_t sifr,gifr,sier,dat[1];

        uint8_t sifr0,sifr1,sifr2,sifr3,sier1,sier0,sier2,sier3;

        wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIFR ,dat);
        gifr = dat[0];
        wk2xxx_write_reg(s->spi_wk,1,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
        wk2xxx_write_reg(s->spi_wk,2,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
        wk2xxx_write_reg(s->spi_wk,3,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
        wk2xxx_write_reg(s->spi_wk,4,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0

        wk2xxx_read_reg(s->spi_wk,1,WK2XXX_SIFR,&sifr0);
        wk2xxx_read_reg(s->spi_wk,2,WK2XXX_SIFR,&sifr1);
        wk2xxx_read_reg(s->spi_wk,3,WK2XXX_SIFR,&sifr2);
        wk2xxx_read_reg(s->spi_wk,4,WK2XXX_SIFR,&sifr3);

        wk2xxx_read_reg(s->spi_wk,1,WK2XXX_SIER,&sier0);
        wk2xxx_read_reg(s->spi_wk,2,WK2XXX_SIER,&sier1);
        wk2xxx_read_reg(s->spi_wk,3,WK2XXX_SIER,&sier2);
        wk2xxx_read_reg(s->spi_wk,4,WK2XXX_SIER,&sier3);

#ifdef _DEBUG_WK2XXX1
    printk(KERN_ALERT "irq_app....gifr:%x  sier1:%x  sier2:%x sier3:%x sier4:%x   sifr1:%x sifr2:%x sifr3:%x sifr4:%x \n",gifr,sier0,sier1,sier2,sier3,sifr0,sifr1,sifr2,sifr3);
#endif
        switch(s->port.iobase)
            {
                case 1 :
                    if(!(gifr & WK2XXX_UT1INT))
                    {
                        return;
                    }
                    break;
                case 2 :
                    if(!(gifr & WK2XXX_UT2INT))
                    {
                        return;
                    }
                    break;
                case 3 :
                    if(!(gifr & WK2XXX_UT3INT))
                    {
                        return;
                    }
                    break;
                case 4 :
                    if(!(gifr & WK2XXX_UT4INT))
                    {
                        return;
                    }
                    break;
                default:
                    break;

            }

        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
        sifr = dat[0];
        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
        sier = dat[0];
#ifdef _DEBUG_WK2XXX1
        printk(KERN_ALERT "irq_app..........sifr:%x sier:%x \n",sifr,sier);
#endif
                do {
                       if ((sifr&WK2XXX_RFTRIG_INT)||(sifr&WK2XXX_RXOVT_INT))
                        {
                               wk2xxx_rx_chars(&s->port);
                        }

                        if ((sifr & WK2XXX_TFTRIG_INT)&&(sier & WK2XXX_TFTRIG_IEN ))
                        {
                               wk2xxx_tx_chars(&s->port);
                                 return;
                        }
                        if (pass_counter++ > WK2XXX_ISR_PASS_LIMIT)
                                break;
                        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
                        sifr = dat[0];
                        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
                        sier = dat[0];
#ifdef _DEBUG_WK2XXX1
    printk(KERN_ALERT "irq_app...........rx............tx  sifr:%x sier:%x port:%x\n",sifr,sier,s->port.iobase);
#endif
               } while ((sifr&WK2XXX_RXOVT_INT)||(sifr & WK2XXX_RFTRIG_INT)||((sifr & WK2XXX_TFTRIG_INT)&&(sier & WK2XXX_TFTRIG_IEN)));
#ifdef _DEBUG_WK2XXX1
    printk(KERN_ALERT "sifr:%d\n",sifr);
#endif
#ifdef _DEBUG_WK2XXX1
    printk(KERN_ALERT "wk2xxxirq_app()---------exit---\n");
#endif

}

/*
 *   Return TIOCSER_TEMT when transmitter is not busy.
 */

static u_int wk2xxx_tx_empty(struct uart_port *port)// or query the tx fifo is not empty?
{
    uint8_t rx;
       mutex_lock(&wk2xxxs_lock);
    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "wk2xxx_tx_empty()---------in---\n");
#endif

    // mutex_lock(&wk2xxxs_lock);
    //s->tx_empty_flag = 1;
    /*if(!(s->tx_empty_flag || s->tx_empty_fail))
    {
        if(wk2xxx_dowork(s))
        {
            s->tx_empty_flag = 1;
 #ifdef _DEBUG_WK2XXX1
          printk(KERN_ALERT "tx_empty_flag=1");
 #endif

        }
        else
        {
 #ifdef _DEBUG_WK2XXX1
           printk(KERN_ALERT "tx_empty_fail=1");
  #endif

            s->tx_empty_fail = 1;
        }
    }*/
if(!(s->tx_empty_flag || s->tx_empty_fail))
{
    wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,&rx);
                 s->tx_empty = (rx & WK2XXX_TDAT)<=0;
        if(s->tx_empty)
    {
    s->tx_empty_flag =0;
    s->tx_empty_fail=0;
    }
    else
    {
    s->tx_empty_fail=0;
    s->tx_empty_flag =0;
    }
}
  #ifdef _DEBUG_WK2XXX4
              printk(KERN_ALERT "s->tx_empty_fail----FSR:%d--s->tx_empty:%d--\n",rx,s->tx_empty);
   #endif

#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "wk2xxx_tx_empty----------exit---\n");
#endif
     mutex_unlock(&wk2xxxs_lock);
    return s->tx_empty;

}

static void wk2xxx_set_mctrl(struct uart_port *port, u_int mctrl)//nothing
{
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_set_mctrl---------exit---\n");
#endif

}
static u_int wk2xxx_get_mctrl(struct uart_port *port)// since no modem control line
{
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_get_mctrl---------exit---\n");
#endif

        return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
}

/*
 *  interrupts disabled on entry
 */

static void wk2xxx_stop_tx(struct uart_port *port)//
{
mutex_lock(&wk2xxxs_lock);

#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_stop_tx------in---\n");
#endif
uint8_t rx;

 //mutex_lock(&wk2xxxs_lock);
    //disable the interrupt,clear the corresponding bit in GIR
    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
        //s->stop_tx_flag = 1;
   /* if(!(s->stop_tx_flag||s->stop_tx_fail))
    {
        if(wk2xxx_dowork(s))
        {
            s->stop_tx_flag =1;
        }
        else
        {
            s->stop_tx_fail =1;
        }
    }*/

if(!(s->stop_tx_flag||s->stop_tx_fail))
          {
    wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
    s->stop_tx_fail=rx&WK2XXX_TFTRIG_IEN>0;
         if(s->stop_tx_fail)
          {

                  wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
                  rx &=~WK2XXX_TFTRIG_IEN;
                  wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
                  wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
                  rx &= ~WK2XXX_TFTRIG_INT;
                  wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
                  s->stop_tx_fail =0;
          s->stop_tx_flag=0;

          }
    else
    {
    s->stop_tx_fail =0;
        s->stop_tx_flag=0;

    }

           }
 //mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX4
    printk(KERN_ALERT "-wk2xxx_stop_tx------exit---\n");
#endif
mutex_unlock(&wk2xxxs_lock);
}

/*
 *  * interrupts may not be disabled on entry
*/
static void wk2xxx_start_tx(struct uart_port *port)
{
//mutex_lock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_start_tx------in---\n");
#endif
    // mutex_lock(&wk2xxxs_lock);
        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
//  uint8_t rx;
    //s->start_tx_flag = 1;
        //vk32xx_dowork(s);
        if(!(s->start_tx_flag||s->start_tx_fail))
        {
            if(wk2xxx_dowork(s))
            {
            s->start_tx_flag = 1;
			#ifdef _DEBUG_tla001
    				printk(KERN_ALERT "****** start_tx_flag=1*****\n");
			#endif
            }
            else
            {
            s->start_tx_fail = 1;
			#ifdef _DEBUG_tla001
    				printk(KERN_ALERT "****** start_tx_fail=1*****\n");
			#endif
            }
        }
// mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "-wk2xxx_start_tx------exit---\n");
#endif
// mutex_unlock(&wk2xxxs_lock);

//                        vk32xx_read_reg(s->spi_vk,s->port.iobase,VK32XX_SIER,&rx);
//                        rx |= VK32XX_TRIEN;
//                        vk32xx_write_reg(s->spi_vk,s->port.iobase,VK32XX_SIER,rx);
}

/*
 *  * Interrupts enabled
*/

static void wk2xxx_stop_rx(struct uart_port *port)
{
//mutex_lock(&wk2xxxs_lock);

#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_stop_rx------in---\n");
#endif
       //   uint8_t rx;
        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
        //s->stop_rx_flag = 1;
        // mutex_lock(&wk2xxxs_lock);
       if(!(s->stop_rx_flag ||s->stop_rx_fail ))
        {
            if(wk2xxx_dowork(s))
            {
                s->stop_rx_flag = 1;
				 #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "****** stop_rx_flag=1*****\n");
				#endif
            }
            else
            {
                s->stop_rx_fail = 1;
				#ifdef _DEBUG_tla001
    				printk(KERN_ALERT "****** stop_rx_fail=1*****\n");
				#endif
            }
        }
/*
if(!(s->stop_rx_flag ||s->stop_rx_fail ))
{
    wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
    s->stop_rx_fail=rx&WK2XXX_RFTRIG_IEN||rx&WK2XXX_RXOUT_IEN>0;
    if(s->stop_rx_fail)
          {
              wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
              rx &=~WK2XXX_RFTRIG_IEN;
                          rx &=~WK2XXX_RXOUT_IEN;
              wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);

              wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
              rx &= ~WK2XXX_RFTRIG_INT;
                          rx &= ~WK2XXX_RXOVT_INT;
              wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
                          s->stop_rx_fail =0;
             s->stop_rx_flag = 0;
        }
else
    {
        s->stop_rx_fail =0;
                s->stop_rx_flag = 0;

    }
}*/
// mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_stop_rx------exit---\n");
#endif
//mutex_unlock(&wk2xxxs_lock);

}

/*
 *  * No modem control lines
 *   */
static void wk2xxx_enable_ms(struct uart_port *port)    //nothing
{
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_enable_ms------exit---\n");
#endif

}
/*
 *  * Interrupts always disabled.
*/
static void wk2xxx_break_ctl(struct uart_port *port, int break_state)
{
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_break_ctl------exit---\n");
#endif

    //break operation, but there  seems no such operation in vk32
}

static int wk2xxx_startup(struct uart_port *port)//i
{
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_startup------in---\n");
#endif

        uint8_t gena,grst,gier,sier,scr,dat[1];
        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
        char b[12];
        if (s->suspending)
            return 0;
//printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s->     irq_flag,s->tx_empty);

        s->force_end_work = 0;
        sprintf(b, "wk2xxx-%d", (uint8_t)s->port.iobase);
    //s->workqueue = create_singlethread_workqueue(b);
    s->workqueue = create_workqueue(b);

        if (!s->workqueue)
       {
            dev_warn(&s->spi_wk->dev, "cannot create workqueue\n");
            return -EBUSY;
        }

        INIT_WORK(&s->work, wk2xxx_work);

        if (s->wk2xxx_hw_suspend)
          s->wk2xxx_hw_suspend(0);
      //wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,0);
      wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,dat);//默认0x30
	  #ifdef _DEBUG_tla001
    		printk(KERN_ALERT "******read WK2XXX_GENA*****0x%x\n",dat[0]);
		#endif
     gena=dat[0];
          switch (s->port.iobase)
    {
          case 1:
                  gena|=WK2XXX_UT1EN;
                  wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,gena);
				  #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "******wk1 write WK2XXX_GENA*****0x%x\n",gena);
					#endif
                  break;
          case 2:
                  gena|=WK2XXX_UT2EN;
                  wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,gena);
					#ifdef _DEBUG_tla001
						printk(KERN_ALERT "******wk2 write WK2XXX_GENA*****0x%x\n",gena);
					#endif
				  break;
          case 3:
                 gena|=WK2XXX_UT3EN;
                 wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,gena);
                  #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "******wk3 write WK2XXX_GENA*****0x%x\n",gena);
					#endif
					break;
          case 4:
                  gena|=WK2XXX_UT4EN;
                  wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,gena);
                 #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "******wk4 write WK2XXX_GENA*****0x%x\n",gena);
					#endif
					break;
          default:
        printk(KERN_ALERT ":con_wk2xxx_subport bad iobase %d\n", (uint8_t)s->port.iobase);
          }

 wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,dat);
           grst=dat[0];
		   #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "******read WK2XXX_GRST*****0x%x\n",grst);
			#endif
           switch (s->port.iobase)
          {
           case 1:
                    grst|=WK2XXX_UT1RST;
                    wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,grst);
                   #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "******wk1 write WK2XXX_GRST*****0x%x\n",grst);
					#endif
					break;
            case 2:
                    grst|=WK2XXX_UT2RST;
                    wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,grst);
                    #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "******wk2 write WK2XXX_GRST*****0x%x\n",grst);
					#endif
					break;
            case 3:
                   grst|=WK2XXX_UT3RST;
                   wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,grst);
                    #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "******wk3 write WK2XXX_GRST*****0x%x\n",grst);
					#endif
					break;
            case 4:
                    grst|=WK2XXX_UT4RST;
                    wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,grst);
                    #ifdef _DEBUG_tla001
    				printk(KERN_ALERT "******wk4 write WK2XXX_GRST*****0x%x\n",grst);
					#endif
					break;
            default:
     printk(KERN_ALERT ":con_wk2xxx_subport bad iobase %d\n", (uint8_t)s->port.iobase);
            }

        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
        sier = dat[0];
        sier &= ~WK2XXX_TFTRIG_IEN;
        sier |= WK2XXX_RFTRIG_IEN;
        sier |= WK2XXX_RXOUT_IEN;
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,sier);

        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,dat);
        scr = dat[0] | WK2XXX_TXEN|WK2XXX_RXEN;
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,scr);

    //initiate the fifos
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_FCR,0x0f);//initiate the fifos
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_FCR,0x0c);
    //enable the sub port interrupt
        wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,dat);
        gier = dat[0];

        switch (s->port.iobase){
        case 1:
                gier|=WK2XXX_UT1IE;
                wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,gier);
                break;
        case 2:
                gier|=WK2XXX_UT2IE;
                wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,gier);
                break;
        case 3:
                gier|=WK2XXX_UT3IE;
                wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,gier);
                break;
        case 4:
                gier|=WK2XXX_UT4IE;
                wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,gier);
                break;
        default:
                printk(KERN_ALERT ": bad iobase %d\n", (uint8_t)s->port.iobase);
              }

        if (s->wk2xxx_hw_suspend)
            s->wk2xxx_hw_suspend(0);
    msleep(50);

        uart_circ_clear(&s->port.state->xmit);
        wk2xxx_enable_ms(&s->port);
      // request irq
        if(request_irq(s->port.irq, wk2xxx_irq,IRQF_SHARED|IRQF_TRIGGER_LOW,"wk2xxxspi", s) < 0)
        {
                dev_warn(&s->spi_wk->dev, "cannot allocate irq %d\n", s->irq);
                s->port.irq = 0;
				#ifdef _DEBUG_tla001
    				printk(KERN_ALERT "****** start_tx_fail=1*****\n");
				#endif
                destroy_workqueue(s->workqueue);
                s->workqueue = NULL;
                return -EBUSY;
        }       udelay(100);
        udelay(100);
#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "-wk2xxx_startup------exit---\n");
#endif

       return 0;
}
//* Power down all displays on reboot, poweroff or halt *

static void wk2xxx_shutdown(struct uart_port *port)//
{

#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "-wk2xxx_shutdown------in---\n");
#endif

    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
    if (s->suspending)
        return;
    s->force_end_work = 1;
    if (s->workqueue)
    {
        flush_workqueue(s->workqueue);
        destroy_workqueue(s->workqueue);
        s->workqueue = NULL;
    }

    if (s->port.irq)
    {
        disable_irq_nosync(s->port.irq);
		printk(KERN_ALERT "irq---%d\n",s->port.line);
        free_irq(s->port.irq,s);
    }
//printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s->     irq_flag,s->tx_empty);
#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "-wk2xxx_shutdown-----exit---\n");
#endif

        return;

}

static void conf_wk2xxx_subport(struct uart_port *port)//i
{
#ifdef _DEBUG_WK2XXX
            printk(KERN_ALERT "-conf_wk2xxx_subport------in---\n");
#endif

        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
    uint8_t old_sier,lcr,scr,scr_ss,dat[1],gena,test1,baud0_ss,baud1_ss,pres_ss;

    lcr = s->new_lcr;
    scr_ss = s->new_scr;
    baud0_ss=s->new_baud0;
    baud1_ss=s->new_baud1;
    pres_ss=s->new_pres;
        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER ,dat);
        old_sier = dat[0];
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER ,old_sier&(~(WK2XXX_TFTRIG_IEN | WK2XXX_RFTRIG_IEN | WK2XXX_RXOUT_IEN)));
    //local_irq_restore(flags);
    do{
        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
        //ssr = dat[0];
       } while (dat[0] & WK2XXX_TBUSY);
        // then, disable everything
        wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,dat);
        scr = dat[0];
        scr &= 0x0f;
        scr |= scr_ss;

        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR ,scr&(~(WK2XXX_RXEN|WK2XXX_TXEN)));
        // set the parity, stop bits and data size //
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_LCR ,lcr);
        // set the baud rate //
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER ,old_sier);
 //       wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR ,scr|(WK2XXX_RXEN|WK2XXX_TXEN));
        // set the baud rate //
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,1);
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD0 ,baud0_ss);
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD1 ,baud1_ss);
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_PRES ,pres_ss);
#ifdef _DEBUG_WK2XXX2
            wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD0,dat);
            printk(KERN_ALERT ":WK2XXX_BAUD0=0x%X\n", dat[0]);
             wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD1,dat);
            printk(KERN_ALERT ":WK2XXX_BAUD1=0x%X\n", dat[0]);
             wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_PRES,dat);
            printk(KERN_ALERT ":WK2XXX_PRES=0x%X\n", dat[0]);
#endif
        wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,0);
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR ,scr|(WK2XXX_RXEN|WK2XXX_TXEN)     );

#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "-conf_wk2xxx_subport------exit---\n");
#endif

}

// change speed
static void wk2xxx_termios( struct uart_port *port, struct ktermios *termios,
            struct ktermios *old)
{
#ifdef _DEBUG_WK2XXX
       printk(KERN_ALERT "-vk32xx_termios------in---\n");
#endif

    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
    int baud = 0;
    uint8_t lcr,scr,baud1,baud0,pres;
    unsigned short cflag;
    unsigned short lflag;
    //u32 param_new, param_mask;
//   mutex_lock(&wk2xxxs_lock);
    cflag = termios->c_cflag;
    lflag = termios->c_lflag;
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "cflag := 0x%X  lflag : = 0x%X\n",cflag,lflag);
#endif
    baud1=0;
    baud0=0;
    pres=0;
    baud = tty_termios_baud_rate(termios);

    switch (baud) {
case 600:
    baud1=0x4;
        baud0=0x7f;
        pres=0;
        break;
    case 1200:
        baud1=0x2;
            baud0=0x3F;
            pres=0;
        break;
    case 2400:
        baud1=0x1;
            baud0=0x1f;
            pres=0;
        break;
    case 4800:
        baud1=0x00;
            baud0=0x8f;
            pres=0;
        break;
    case 9600:
        baud1=0x00;
            baud0=0x47;
            pres=0;
        break;
    case 19200:
        baud1=0x00;
            baud0=0x23;
            pres=0;
        break;
    case 38400:
        baud1=0x00;
            baud0=0x11;
            pres=0;
        break;
    case 76800:
           baud1=0x00;
            baud0=0x08;
            pres=0;
         break; 

        case 1800:
        baud1=0x01;
        baud0=0x7f;
        pres=0;
                break;
        case 3600:
        baud1=0x00;
        baud0=0xbf;
        pres=0;
                break;
        case 7200:
        baud1=0x00;
        baud0=0x5f;
        pres=0;
                break;
        case 14400:
        baud1=0x00;
        baud0=0x2f;
        pres=0;
                break;
        case 28800:
        baud1=0x00;
        baud0=0x17;
        pres=0;
                break;
        case 57600:
        baud1=0x00;
        baud0=0x0b;
        pres=0;
                break;
    case 115200:
        baud1=0x00;
        baud0=0x05;
        pres=0;
		#ifdef _DEBUG_tla001
    			printk(KERN_ALERT "set baud=115200bps\n");
		#endif
        break;
    case 230400:
        baud1=0x00;
        baud0=0x02;
        pres=0;
        break;
    default:
        baud1=0x00;
        baud0=0x00;
        pres=0;
    }
    tty_termios_encode_baud_rate(termios, baud, baud);

    /* we are sending char from a workqueue so enable */

    //spin_lock(&s->conf_lock);

    //s->port.state->port.tty->low_latency = 1;
    //termios->c_lflag &= ~ECHO;

        lcr =0;
        if (cflag & CSTOPB)
                lcr|=WK2XXX_STPL;//two  stop_bits
        else
                lcr&=~WK2XXX_STPL;//one  stop_bits

        if (cflag & PARENB) {
                lcr|=WK2XXX_PAEN;//enbale spa
                if (!(cflag & PARODD)){
                        lcr |= WK2XXX_PAM0;//PAM0=1
                        lcr &= ~WK2XXX_PAM0;//PAM1=0
                }
                else{
                        lcr |= WK2XXX_PAM1;
                        lcr &= ~WK2XXX_PAM0;
                }
        }
        else{
                lcr&=~WK2XXX_PAEN;
        }

    //scr = 0;
    //scr &= 0x0f;
    //scr |= param_new<<4;
    s->new_baud1=baud1;
    s->new_baud0=baud0;
    s->new_pres=pres;

    //spin_lock(&s->conf_lock);
    //s->conf_flag =1;
    s->new_lcr = lcr;
    s->new_scr = scr;
    //spin_unlock(&s->conf_lock);
    //vk32xx_dowork(s);

    if(!(s->conf_flag|| s->conf_fail))
    {
    if(wk2xxx_dowork(s))
    {
        s->conf_flag =1;
    }
    else
    {
        s->conf_fail =1;
    }

    }
#ifdef _DEBUG_WK2XXX
      printk(KERN_ALERT "-vk32xx_termios------exit---\n");
#endif
    // mutex_unlock(&wk2xxxs_lock);
     return ;

}

static const char *wk2xxx_type(struct uart_port *port)
{

#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "wk2xxx_type-------------out-------- \n");
#endif
        return port->type == PORT_WK2XXX ? "wk2xxx" : NULL;//this is defined in serial_core.h
}

/*
* Release the memory region(s) being used by 'port'.
*/
static void wk2xxx_release_port(struct uart_port *port)
{
        printk(KERN_ALERT "wk2xxx_release_port\n");
//  struct vk32xx_port *s = container_of(port,struct vk32xx_port,port);
//  dev_dbg(&s->spi_vk->dev, "%s\n", __func__);
        //no such memory region for vk32
}

/*
* Request the memory region(s) being used by 'port'.
*/
static int wk2xxx_request_port(struct uart_port *port)//no such memory region needed for vk32
{
        printk(KERN_ALERT "wk2xxx_request_port\n");
//        struct vk32xx_port *s = container_of(port,struct vk32xx_port,port);
        return 0;
}

/*
* Configure/autoconfigure the port*/
static void wk2xxx_config_port(struct uart_port *port, int flags)
{
        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);

#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "wk2xxx_config_port \n");
#endif

        if (flags & UART_CONFIG_TYPE && wk2xxx_request_port(port) == 0)
               s->port.type = PORT_WK2XXX;
}

/*
* Verify the new serial_struct (for TIOCSSERIAL).
* The only change we allow are to the flags and type, and
* even then only between PORT_vk32xx and PORT_UNKNOWN
*/
static int wk2xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
{

#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "wk2xxx_verify_port \n");
#endif
        int ret = 0;
        if (ser->type != PORT_UNKNOWN && ser->type != PORT_WK2XXX)
                ret = -EINVAL;
        if (port->irq != ser->irq)
                ret = -EINVAL;
        if (ser->io_type != SERIAL_IO_PORT)
                ret = -EINVAL;
        //if (port->uartclk / 16 != ser->baud_base)//?a??2?猫路?篓
        //      ret = -EINVAL;
        if (port->iobase != ser->port)
                ret = -EINVAL;
        if (ser->hub6 != 0)
                ret = -EINVAL;
        return ret;
}

static struct uart_ops wk2xxx_pops = {
        tx_empty:       wk2xxx_tx_empty,
        set_mctrl:      wk2xxx_set_mctrl,
        get_mctrl:      wk2xxx_get_mctrl,
        stop_tx:        wk2xxx_stop_tx,
        start_tx:       wk2xxx_start_tx,
        stop_rx:        wk2xxx_stop_rx,
        enable_ms:      wk2xxx_enable_ms,
        break_ctl:      wk2xxx_break_ctl,
        startup:        wk2xxx_startup,
        shutdown:       wk2xxx_shutdown,
    set_termios:    wk2xxx_termios,
        type:           wk2xxx_type,
        release_port:   wk2xxx_release_port,
        request_port:   wk2xxx_request_port,
        config_port:    wk2xxx_config_port,
        verify_port:    wk2xxx_verify_port,

};
static struct uart_driver wk2xxx_uart_driver = {

        owner:                  THIS_MODULE,
        major:               SERIAL_WK2XXX_MAJOR,
#ifdef CONFIG_DEVFS_FS
        driver_name:            "ttySWK",
        dev_name:               "ttysWK",
#else
        driver_name:            "ttySWK",
        dev_name:               "ttysWK",
#endif
        minor:                  MINOR_START,
        nr:                     NR_PORTS,
        cons:                   NULL//WK2Xxx_CONSOLE,
};

static int uart_driver_registered;

int wk2166_irq1;

static int __devinit wk2xxx_probe(struct spi_device *spi)
{
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_probe()------in---\n");
#endif

    uint8_t i;
    int status;
	i=0;

   /* static volatile unsigned long *gpbcon_addr;
    #define GPBCONWWWWW 0xE020004C
    gpbcon_addr = ioremap(GPBCONWWWWW, 4);
        status = *gpbcon_addr;
        printk(KERN_ERR "GPB_DRV...........= 0x%X\n",status);
    *gpbcon_addr |= 0xaa00;
        status = *gpbcon_addr;
        printk(KERN_ERR "GPB_DRV...........= 0x%X\n",status);
        printk(KERN_ALERT "wk2xxx_probe wk2xxx\n");*/

    mutex_lock(&wk2xxxs_lock);
    if(!uart_driver_registered)
    {
        uart_driver_registered = 1;
            status=uart_register_driver(&wk2xxx_uart_driver);
        if (status)
        {
            printk(KERN_ALERT "Couldn't register wk2xxx uart driver\n");
            mutex_unlock(&wk2xxxs_lock);
            return status;
        }
       }
                printk(KERN_ALERT "wk2xxx_serial_init()\n");

	/********IO初始化***********/
	gpio_free(wk2166_irq);
	gpio_request(wk2166_irq,"wk2166_irq");
	gpio_direction_input(wk2166_irq);
	wk2166_irq1=gpio_to_irq(wk2166_irq);
	 printk(KERN_ALERT "wk2166_irq1=%d\n",wk2166_irq1);
    for(i =0;i<NR_PORTS;i++)
    {
        struct wk2xxx_port *s = &wk2xxxs[i];//container_of(port,struct vk32xx_port,port);
        s->tx_done =0;
        s->spi_wk    = spi;
        s->port.line = i;
        s->port.ops = &wk2xxx_pops;
        s->port.uartclk = WK_CRASTAL_CLK;
        s->port.fifosize = 256;
        s->port.iobase = i+1;
        s->port.irq    = wk2166_irq1;
        s->port.iotype = SERIAL_IO_PORT;
        s->port.flags  = ASYNC_BOOT_AUTOCONF;
        //s->minor       = i;
                status = uart_add_one_port(&wk2xxx_uart_driver, &s->port);
                if(status<0)
                {
                 //dev_warn(&spi->dev,"uart_add_one_port failed for line i:= %d with error %d\n",i,status);
                 printk(KERN_ALERT "uart_add_one_port failed for line i:= %d with error %d\n",i,status);
        }
    }
    printk(KERN_ALERT "uart_add_one_port = 0x%d\n",status);
    mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
       // while(1)
      //  wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,0XFF);
    printk(KERN_ALERT "-wk2xxx_probe()------exit---\n");
#endif
        return 0;

}

/*
static int vk32xx_suspend(struct spi_device *spi)
{
    printk(KERN_ALERT "vk32xx_suspend vk32xx");
    return 0;

}
*/
static int __devexit wk2xxx_remove(struct spi_device *spi)
{

    //struct wk2xxx_port *s = dev_get_drvdata(&spi->dev);
    int i;
#ifdef _DEBUG_WK2XXX
        printk(KERN_ALERT "-wk2xxx_remove()------in---\n");
#endif

    mutex_lock(&wk2xxxs_lock);
    for(i =0;i<NR_PORTS;i++)
    {
        struct wk2xxx_port *s = &wk2xxxs[i];
    uart_remove_one_port(&wk2xxx_uart_driver, &s->port);
    }
    printk(KERN_ALERT "removing wk2xxx driver\n");
    uart_unregister_driver(&wk2xxx_uart_driver);
    mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
    printk(KERN_ALERT "-wk2xxx_remove()------exit---\n");
#endif
/***********释放中断号*************************/
	free_irq(wk2166_irq1,1);
	gpio_free(wk2166_irq);
    return 0;
}

static int wk2xxx_resume(struct spi_device *spi)
{
    printk(KERN_ALERT "resume wk2xxx");
    return 0;
}

static struct spi_driver wk2xxx_driver = {
        .driver = {
                .name           = "wk2166",
                .bus            = &spi_bus_type,
                .owner          = THIS_MODULE,
        },

        .probe          = wk2xxx_probe,
        .remove         = __devexit_p(wk2xxx_remove),
        .resume         = wk2xxx_resume,
};

static int __init wk2xxx_init(void)
{

        int retval;
		mxc_iomux_v3_setup_pad(MX6Q_PAD_SD3_DAT2__GPIO_7_6);
		//mxc_iomux_v3_setup_pad(MX6Q_PAD_SD3_CMD__GPIO_7_2);
		 mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_CS0__ECSPI2_SCLK);
		 mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_CS1__ECSPI2_MOSI);
		 mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_OE__ECSPI2_MISO);
	 	mxc_iomux_v3_setup_pad(MX6Q_PAD_CSI0_DAT11__GPIO_5_29);
		__gpio_set_value(wk2166__cs,1);
        retval = spi_register_driver(&wk2xxx_driver);
        printk(KERN_ALERT "rgister spi return v = :%d\n",retval);
    return retval;
}

static void __exit wk2xxx_exit(void)
{
        spi_unregister_driver(&wk2xxx_driver);
        printk(KERN_ALERT "TEST_REG:quit ");
}

module_init(wk2xxx_init);
module_exit(wk2xxx_exit);

MODULE_AUTHOR("WKIC Ltd");
MODULE_DESCRIPTION("wk2xxx generic serial port driver");
MODULE_LICENSE("GPL");

  wkXXX.h

#ifndef	 _SERIAL_WK2166_H
#define  _SERIAL_WK2166_H

//#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/console.h>
//#include <linux/serial_core.h>

#include <asm/irq.h>
#include <asm/io.h>

//#include <asm/hardware.h>

//EINT15 GPG7
//wkxxxx  Global rigister address defines
#define 	WK2XXX_GENA     0X00		//全局控制寄存器
#define 	WK2XXX_GRST     0X01		//全局子串口复位寄存器
#define		WK2XXX_GMUT     0X02
#define 	WK2XXX_GIER     0X10		//全局中断寄存器
#define 	WK2XXX_GIFR     0X11		//全局中断标志寄存器
#define 	WK2XXX_GPDIR    0X21
#define 	WK2XXX_GPDAT    0X31
#define 	WK2XXX_GPORT    1			//
//wkxxxx  slave uarts  rigister address defines

#define 	WK2XXX_SPAGE    0X03		//子串口页控制寄存器
//PAGE0
#define 	WK2XXX_SCR      0X04		//子串口使能寄存器
#define 	WK2XXX_LCR      0X05		//子串口配置寄存器
#define 	WK2XXX_FCR      0X06		//子串口FIFO控制寄存器
#define 	WK2XXX_SIER     0X07		//子串口中断使能寄存器
#define 	WK2XXX_SIFR     0X08		//子串口中断标志寄存器
#define 	WK2XXX_TFCNT    0X09		//子串口发送FIFO计数寄存器
#define 	WK2XXX_RFCNT    0X0A		//子串口接收FIFO计数寄存器
#define 	WK2XXX_FSR      0X0B		//子串口FIFO状态寄存器
#define 	WK2XXX_LSR      0X0C		//子串口接收状态寄存器
#define 	WK2XXX_FDAT     0X0D		//子串口FIFO数据寄存器
#define 	WK2XXX_FWCR     0X0E		//
#define 	WK2XXX_RS485    0X0F		//
//PAGE1
#define 	WK2XXX_BAUD1    0X04		//子串口波特率配置寄存器高字节
#define 	WK2XXX_BAUD0    0X05		//子串口波特率配置寄存器低字节
#define 	WK2XXX_PRES     0X06		//子串口波特率配置寄存器小数部分
#define 	WK2XXX_RFTL     0X07		//子串口接收FIFO中断触发点配置寄存器
#define 	WK2XXX_TFTL     0X08		//子串口发送FIFO中断触发点配置寄存器
#define 	WK2XXX_FWTH     0X09		//
#define 	WK2XXX_FWTL     0X0A		//
#define 	WK2XXX_XON1     0X0B		//
#define 	WK2XXX_XOFF1    0X0C		//
#define 	WK2XXX_SADR     0X0D		//
#define 	WK2XXX_SAEN     0X0D		//
#define 	WK2XXX_RRSDLY   0X0F		//

/******全局控制寄存器GENA******/
#define 	WK2XXX_UT4EN	0x08		//子串口4时钟使能位
#define 	WK2XXX_UT3EN	0x04		//子串口3时钟使能位
#define 	WK2XXX_UT2EN	0x02		//子串口2时钟使能位
#define 	WK2XXX_UT1EN	0x01		//子串口1时钟使能位
/***全局子串口复位寄存器GRST***/
#define 	WK2XXX_UT4SLEEP	0x80		//子串口4休眠状态位
#define 	WK2XXX_UT3SLEEP	0x40		//子串口3休眠状态位
#define 	WK2XXX_UT2SLEEP	0x20		//子串口2休眠状态位
#define 	WK2XXX_UT1SLEEP	0x10		//子串口1休眠状态位
#define 	WK2XXX_UT4RST	0x08		//子串口4软复位控制位
#define 	WK2XXX_UT3RST	0x04		//子串口3软复位控制位
#define 	WK2XXX_UT2RST	0x02		//子串口2软复位控制位
#define 	WK2XXX_UT1RST	0x01		//子串口1软复位控制位
/******全局中断寄存器GIER******/
#define 	WK2XXX_UT4IE	0x08		//子串口4中断使能控制位
#define 	WK2XXX_UT3IE	0x04		//子串口3中断使能控制位
#define 	WK2XXX_UT2IE	0x02		//子串口2中断使能控制位
#define 	WK2XXX_UT1IE	0x01		//子串口1中断使能控制位
/****全局中断标志寄存器GIFR****/
#define 	WK2XXX_UT4INT	0x08		//子串口4中断标志位
#define 	WK2XXX_UT3INT	0x04		//子串口3中断标志位
#define 	WK2XXX_UT2INT	0x02		//子串口2中断标志位
#define 	WK2XXX_UT1INT	0x01		//子串口1中断标志位
/****子串口页控制寄存器SPAGE***/
#define 	WK2XXX_SPAGE0	0x00		//PAGE0
#define 	WK2XXX_SPAGE1   0x01		//PAGE1
/*****子串口控制寄存器SCR******/
#define 	WK2XXX_SLEEPEN	0x04		//子串口休眠使能位
#define 	WK2XXX_TXEN     0x02		//子串口发送使能位
#define 	WK2XXX_RXEN     0x01		//子串口接收使能位
/*****子串口配置寄存器LCR******/
#define 	WK2XXX_BREAK	0x20		//子串口Line-Break输出控制位
#define 	WK2XXX_IREN     0x10		//子串口红外使能位
#define 	WK2XXX_PAEN     0x08		//子串口校验使能位
#define 	WK2XXX_PAM1     0x04		//子串口校验模式选择位00:0 校验;01:奇校验;
#define 	WK2XXX_PAM0     0x02		//子串口校验模式选择位10:偶校验;11:1 校验
#define 	WK2XXX_STPL     0x01		//子串口停止位长度控制位0:1bit;1:2bit

/****子串口FIFO控制寄存FRC*****/

/****子串口FIFO控制寄存SIER****/
#define 	WK2XXX_FERR_IEN      0x80	//接收FIFO数据错误中断使能位
#define 	WK2XXX_CTS_IEN       0x40	//
#define 	WK2XXX_RTS_IEN       0x20	//
#define 	WK2XXX_XOFF_IEN      0x10	//
#define 	WK2XXX_TFEMPTY_IEN   0x08	//发送FIFO空中断使能位
#define 	WK2XXX_TFTRIG_IEN    0x04	//发送FIFO触点中断使能位
#define 	WK2XXX_RXOUT_IEN     0x02	//接收FIFO超时中断使能位
#define 	WK2XXX_RFTRIG_IEN    0x01	//接收FIFO触点中断使能位
/****子串口FIFO控制寄存SIFR****/
#define 	WK2XXX_FERR_INT      0x80	//接收FIFO数据错误中断标志位
#define 	WK2XXX_CTS_INT       0x40	//
#define 	WK2XXX_RTS_INT       0x20	//
#define 	WK2XXX_XOFF_INT      0x10	//
#define 	WK2XXX_TFEMPTY_INT   0x08	//发送FIFO空中断标志位
#define 	WK2XXX_TFTRIG_INT    0x04	//发送FIFO触点中断标志位
#define 	WK2XXX_RXOVT_INT     0x02	//接收FIFO超时中断标志位
#define 	WK2XXX_RFTRIG_INT    0x01	//接收FIFO触点中断标志位

/*子串口发送FIFO计数寄存器TFCNT*/

/**子串口接收FIFO计数寄存RFCNT**/

/****子串口FIFO 状态寄存FSR****/
#define 	WK2XXX_RFOE     0x80		//子串口接收FIFO中数据溢出出错标志位
#define 	WK2XXX_RFBI     0x40		//子串口接收FIFO中数据有Line-Break错误
#define 	WK2XXX_RFFE     0x20		//子串口接收FIFO中数据帧错误标志位
#define 	WK2XXX_RFPE     0x10		//子串口接收FIFO中数据校验错误标志位
#define 	WK2XXX_RDAT     0x08		//子串口接收FIFO空标志位
#define 	WK2XXX_TDAT     0x04		//子串口发送FIFO空标志位
#define 	WK2XXX_TFULL    0x02		//子串口发送FIFO满标志位
#define 	WK2XXX_TBUSY    0x01		//子串口发送TX忙标志位
/***子串口接收状态寄存器LSR****/
#define 	WK2XXX_OE       0x08		//子串口接收FIFO当前被读取的字节溢出出错标志位
#define 	WK2XXX_BI       0x04		//子串口接收FIFO中当前被读取字节Line-Break错误标志位
#define 	WK2XXX_FE       0x02		//子串口接收FIFO中当前被读取字节帧错误标志位
#define 	WK2XXX_PE       0x01		//子串口接收FIFO中当前被读取字节校验错误标志位
//FWCR
//RS485

//
#define 	NR_PORTS 	4

//
#define 	SERIAL_WK2XXX_MAJOR	    	207
#define 	CALLOUT_WK2XXX_MAJOR		208
#define 	MINOR_START		        5

//wk2xxx hardware configuration

#define 	IRQ_WK2XXX_PIN		IMX_GPIO_NR(5, 17)
#define 	IRQ_WK2XXX				__gpio_to_irq(IRQ_WK2XXX_PIN)//shuould be IRQ_EINT7,but EINT7 of the borad is ocuppied
#define 	WK_CS_PIN 				IMX_GPIO_NR(2, 26)//should be GPB
#define 	WK_CRASTAL_CLK		(3686400*2)
#define 	WK2XXX_CS            	WK_CS_PIN
#define         MAX_WK2XXX           	4

#define 	WK2XXX_ISR_PASS_LIMIT	50

//#define _DEBUG_WK2XXX

#define		PORT_WK2XXX             1
#endif

如果cs信号不能拉低,需要手动拉低,并在spi传输的时候,加锁,不然4路同时读写的时候会冲突 

此外,针对不同的外置晶振,需要重新配置波特率的控制字 

IMX6下移植WKxxx驱动的更多相关文章

  1. 第一章 Android系统移植与驱动开发概述

    本书第一章首先简单概要地介绍了关于Android系统移植和驱动开发的相关内容. 所谓“移植”是指为特定的自己的设备,如手机定制Android的过程.自己开发一些程序(移植)装载在设备上,使得Andro ...

  2. 第一章Android系统移植与驱动开发概述--读书笔记

    以前,初步学习过嵌入式Linux驱动开发的基础课程,对于驱动开发可以说是有了一点点微末的基础吧.首先我们要对Android嵌入式系统有一个初步的认识,Android系统发展到今天已经具备了完善的架构. ...

  3. 1Android系统移植与驱动开发概述

    1.Android系统架构分为四层,从下至上依次为Linux内核层,C/C++代码库.Android SDK API.应用程序,要熟悉每一层的内容以及功能: 2.Android移植分为应用移植和系统移 ...

  4. Android系统移植与驱动开发----第一章

    第一章 Android系统移植与驱动开发 Android源代码定制完全属于自己的嵌入式系统,但是支持的设备不多,所以要移植,而在移植的过程中使用的不得不提的是驱动开发. Android系统构架主要包括 ...

  5. 【转】 linux内核移植和驱动添加(三)

    原文网址:http://blog.chinaunix.net/uid-29589379-id-4708909.html 原文地址:linux内核移植和驱动添加(三) 作者:genehang 四,LED ...

  6. 3.移植驱动到3.4内核-移植DM9000C驱动

    在上章-使内核支持烧写yaffs2,裁剪内核并制作补丁了 本章,便开始移植以前2.6内核的驱动到3.4新内核 1.介绍 首先内核更新,有可能会重新定义新的宏,去除以前的宏,以前更改函数名等 所以移植驱 ...

  7. backports移植rtlwifi驱动

    /************************************************************************ * backports移植rtlwifi驱动 * 说 ...

  8. 基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九)

    作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...

  9. I.mx6s上移植wm8960驱动(基于linux3.0.101版本)

    I.mx6s上移植wm8960驱动   此篇博文只记录移植的步骤,其他不做分析.首先上一张wm8960的硬件连接图: 1  上电操作   配置wm8960的上电脚,文件位置:arch/arm/mach ...

随机推荐

  1. No mapping found for HTTP request with URI

    原因:spring-mvc 的xml配置文件的包名配置错误 <mvc:annotation-driven /> <context:component-scan base-packag ...

  2. How to implement updatable view with NHibernate

    see : http://msdn.microsoft.com/en-us/library/ms187956.aspx(The constrains of creation updatable vie ...

  3. Python 基礎 - 數據類型

    標準數據類型 Python3 中有六個標準的數據類型 1 Number(數字) 2 String(字符串) 3 List (列表) 4 Tuple (元組) 5 Sets (集合) 6 Diction ...

  4. Canvas旋转元素

    Canvas是HTML5的画布元素,有时需要按指定角度旋转某一个元素. var canvas = document.getElementById("mycanvas"); var ...

  5. LintCode Binary Tree Inorder Traversal

    Binary Tree Inorder Traversal Given a binary tree, return the inorder traversal of its nodes' values ...

  6. 动态添加Marquee标签,并动态赋值与属性

    前台加载js $(function(){ var publishStr="<%=publishText%>" var marqueeStr=" <mar ...

  7. select 通过jq赋值

    <select name="F_YSBAQLX" onchange="selectvalue()" id="lista" prompt ...

  8. Python变量、数据类型6

    1.Python变量 变量,即代表某个value的名字. 变量的值存储在内存中,这意味着在创建变量时会在内存中开辟一个空间. !!!即值并没有保存在变量中,它们保存在计算机内存的深处,被变量引用.所以 ...

  9. windows环境下 svn 客户端

      

  10. TTS多音字问题

    今天在CSDN上找到了解决方案,终于解决了多音字问题.   Text1.Text = "<pron sym='jia 3'> 贾</pron>宝玉,商<pron ...