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. WPF之MVVM模式讲解

    WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI. 恰当的模式可以让我们轻松达到“高内聚 ...

  2. Javascript实现CheckBox的全选与取消全选的代码(转)

    js函数 复制代码 代码如下: <script type="text/javascript"> function checkAll(name) { var el = d ...

  3. OrCAD搭建Access数据库

    刚进入到一个小公司,接到的第一个电路设计的案子是从零开始的,辛苦就不说,关键是这么不严谨,容易出错,于是乎,问题来了,能否从零开始着手建立个类似于以前公司的数据库,管理原理图封装,PCB封装及规格书! ...

  4. 关于重定向urlrewriter.urlmapping

    大家都知道web.config 中的 urlMappings怎么用 <system.web> <urlMappings enabled="true"> &l ...

  5. [SQL Basics] Indexes

    An index is used to speed up searching in the database. By default, when you create this table, your ...

  6. iOS Xcodebuild

    简介 xcodebuild 是苹果发布自动构建的工具.它在一个Xcode项目下能构建一个或者多个targets ,也能在一个workspace或者Xcode项目上构建scheme,总的来说,用它没错就 ...

  7. 从零开始学习Node.js例子七 发送HTTP客户端请求并显示响应结果

    wget.js:发送HTTP客户端请求并显示响应的各种结果 options对象描述了将要发出的请求.data事件在数据到达时被触发,error事件在发生错误时被触发.HTTP请求中的数据格式通过MIM ...

  8. 分支语句 if的嵌套 循环语句

    0930 今天学习内容做以下总结: 语句的分类:顺序语句,分支语句(选择,条件),循环语句 分支语句 格式1:if(表达式(要么是true 要么是false)){} 格式2:if(){}slse{}  ...

  9. httpd启动脚本

    #!/bin/bash # chkconfig: - . /etc/rc.d/init.d/functions if [ -f /etc/sysconfig/httpd ]; then . /etc/ ...

  10. PHPSTORM支持dwt文件设置方法