Android9.0 mtk SPI转串口驱动调试 wk2124

 
diff --git a/kernel-4.4/drivers/spi/Kconfig b/kernel-4.4/drivers/spi/Kconfig
old mode 100644
new mode 100755
index 19043cadab2ad415207434954eaf6a813004d45c..59eb9c67e8a58516e597954496e7e2c6d5705930
--- a/kernel-4.4/drivers/spi/Kconfig
+++ b/kernel-4.4/drivers/spi/Kconfig
@@ -707,6 +707,14 @@ config SPI_TLE62X0
 	  sysfs interface, with each line presented as a kind of GPIO
 	  exposing both switch control and diagnostic feedback.
 
+#config WK2XXX_SPI
+#	tristate "wk2124  SPI to uart controller"
+#	#depends on SPI
+#	default n
+#	---help---
+#	  This selects the wk2124 SPI bus driver.
+#	  If you want to use MediaTek(R) SPI interface, say Y or M here.  If unsure, say N.
+
 #
 # Add new SPI protocol masters in alphabetical order above this line
 #
diff --git a/kernel-4.4/drivers/spi/Makefile b/kernel-4.4/drivers/spi/Makefile
old mode 100644
new mode 100755
index b1bd4f903d8a5c19610aa9f990c9744fd7043fe1..a8c0b7205b4a39099b993e437870a402cf2edb5c
--- a/kernel-4.4/drivers/spi/Makefile
+++ b/kernel-4.4/drivers/spi/Makefile
@@ -102,3 +102,5 @@ obj-$(CONFIG_SPI_XTENSA_XTFPGA)		+= spi-xtensa-xtfpga.o
 obj-$(CONFIG_SPI_ZYNQMP_GQSPI)		+= spi-zynqmp-gqspi.o
 # mediatek
 obj-$(CONFIG_MTK_SPI)	+= mediatek/
+obj-y	+= wk2xxx_spi.o
+#obj-$(CONFIG_WK2XXX_SPI)	+= wk2xxx_spi.o
diff --git a/kernel-4.4/drivers/spi/wk2xxx.h b/kernel-4.4/drivers/spi/wk2xxx.h
new file mode 100755
index 0000000000000000000000000000000000000000..9e6c9c57dd3b6c69ca6247f315baf86e5ebff633
--- /dev/null
+++ b/kernel-4.4/drivers/spi/wk2xxx.h
@@ -0,0 +1,176 @@
+
+/*
+*	WKIC Ltd.
+*	WK2xxx.c
+*	wk2xxx_GPIO_I2C DEMO Ver
+
+ion :1.0 Data:2018-08-08
+*	By  xuxunwei Tech 
+*
+*/
+#ifndef	_SERIAL_WK2XXX_H       //_SERIAL_WK2XXX_H
+#define  _SERIAL_WK2XXX_H
+	
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <asm/irq.h>
+
+
+
+/*****************************
+***wkxxxx  Global register 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
+
+
+/*****************************
+*wkxxxx  slave uarts  register address defines
+******************************/
+#define 	WK2XXX_SPAGE    0X03
+#define 	WK2XXX_PAGE1    1
+#define 	WK2XXX_PAGE0    0
+
+/*PAGE0*/
+#define 	WK2XXX_SCR      0X04
+#define 	WK2XXX_LCR      0X05
+#define 	WK2XXX_FCR      0X06
+#define 	WK2XXX_SIER     0X07
+#define 	WK2XXX_SIFR     0X08
+#define 	WK2XXX_TFCNT    0X09
+#define 	WK2XXX_RFCNT    0X0A
+#define 	WK2XXX_FSR      0X0B
+#define 	WK2XXX_LSR      0X0C
+#define 	WK2XXX_FDAT     0X0D
+#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
+#define 	WK2XXX_TFTL     0X08
+#define 	WK2XXX_FWTH     0X09
+#define 	WK2XXX_FWTL     0X0A
+#define 	WK2XXX_XON1     0X0B
+#define 	WK2XXX_XOFF1    0X0C
+#define 	WK2XXX_SADR     0X0D
+#define 	WK2XXX_SAEN     0X0E
+#define 	WK2XXX_RRSDLY   0X0F
+
+
+//wkxxx register bit defines
+/*GENA register*/
+#define 	WK2XXX_UT4EN	  0x08
+#define 	WK2XXX_UT3EN	  0x04
+#define 	WK2XXX_UT2EN	  0x02
+#define 	WK2XXX_UT1EN	  0x01
+/*GRST register*/
+#define 	WK2XXX_UT4SLEEP	0x80
+#define 	WK2XXX_UT3SLEEP	0x40
+#define 	WK2XXX_UT2SLEEP	0x20
+#define 	WK2XXX_UT1SLEEP	0x10
+#define 	WK2XXX_UT4RST	    0x08
+#define 	WK2XXX_UT3RST		0x04
+#define 	WK2XXX_UT2RST		0x02
+#define 	WK2XXX_UT1RST		0x01
+/*GIER register*/
+#define 	WK2XXX_UT4IE		0x08
+#define 	WK2XXX_UT3IE		0x04
+#define 	WK2XXX_UT2IE		0x02
+#define 	WK2XXX_UT1IE		0x01
+/*GIFR register*/
+#define 	WK2XXX_UT4INT		0x08
+#define 	WK2XXX_UT3INT		0x04
+#define 	WK2XXX_UT2INT		0x02
+#define 	WK2XXX_UT1INT		0x01
+/*SPAGE register*/
+#define 	WK2XXX_SPAGE0	    0x00
+#define 	WK2XXX_SPAGE1     0x01
+/*SCR register*/
+#define 	WK2XXX_SLEEPEN    0x04
+#define 	WK2XXX_TXEN       0x02
+#define 	WK2XXX_RXEN       0x01
+/*LCR register*/
+#define 	WK2XXX_BREAK	  0x20
+#define 	WK2XXX_IREN     0x10
+#define 	WK2XXX_PAEN     0x08
+#define 	WK2XXX_PAM1     0x04
+#define 	WK2XXX_PAM0     0x02
+#define 	WK2XXX_STPL     0x01
+/*FCR register*/
+#define 	WK2XXX_TFEN     0x08
+#define 	WK2XXX_RFEN     0x04
+#define 	WK2XXX_TFRST    0x02
+#define 	WK2XXX_RFRST    0x01
+/*SIER register*/
+#define 	WK2XXX_FERR_IEN      0x80
+#define 	WK2XXX_CTS_IEN       0x40
+#define 	WK2XXX_RTS_IEN       0x20
+#define 	WK2XXX_XOFF_IEN      0x10
+#define 	WK2XXX_TFEMPTY_IEN   0x08
+#define 	WK2XXX_TFTRIG_IEN    0x04
+#define 	WK2XXX_RXOUT_IEN     0x02
+#define 	WK2XXX_RFTRIG_IEN    0x01
+/*SIFR register*/
+#define 	WK2XXX_FERR_INT      0x80
+#define 	WK2XXX_CTS_INT       0x40
+#define 	WK2XXX_RTS_INT       0x20
+#define 	WK2XXX_XOFF_INT      0x10
+#define 	WK2XXX_TFEMPTY_INT   0x08
+#define 	WK2XXX_TFTRIG_INT    0x04
+#define 	WK2XXX_RXOVT_INT     0x02
+#define 	WK2XXX_RFTRIG_INT    0x01
+
+/*TFCNT register*/
+/*RFCNT register*/
+/*FSR register*/
+#define 	WK2XXX_RFOE      0x80
+#define 	WK2XXX_RFBI      0x40
+#define 	WK2XXX_RFFE      0x20
+#define 	WK2XXX_RFPE      0x10
+#define 	WK2XXX_RDAT      0x08
+#define 	WK2XXX_TDAT      0x04
+#define 	WK2XXX_TFULL     0x02
+#define 	WK2XXX_TBUSY     0x01
+/*LSR register*/
+#define 	WK2XXX_OE        0x08
+#define 	WK2XXX_BI        0x04
+#define 	WK2XXX_FE        0x02
+#define 	WK2XXX_PE        0x01
+/*FWCR register*/
+#define 	WK2XXX_RTS       0x02
+#define 	WK2XXX_CTS       0x01
+/*RS485 register*/
+#define 	WK2XXX_RSRS485   0x40
+#define 	WK2XXX_ATADD     0x20
+#define 	WK2XXX_DATEN     0x10
+#define 	WK2XXX_RTSEN     0x02
+#define 	WK2XXX_RTSINV    0x01
+
+
+
+//
+#define 	NR_PORTS 	4
+
+//
+#define 	SERIAL_WK2XXX_MAJOR	    	207
+#define 	CALLOUT_WK2XXX_MAJOR		  208	
+#define 	MINOR_START		            5
+//wk2xxx hardware configuration
+#define		wk2xxx_spi_speed	 1000000 //10000000
+#define 	IRQ_WK2XXX		    GPIO7_A2
+#define 	WK_CRASTAL_CLK		(3686400*2)
+#define     MAX_WK2XXX           	4
+#define 	WK2XXX_ISR_PASS_LIMIT	50
+#define		PORT_WK2XXX            1
+#endif
+
diff --git a/kernel-4.4/drivers/spi/wk2xxx_spi.c b/kernel-4.4/drivers/spi/wk2xxx_spi.c
new file mode 100755
index 0000000000000000000000000000000000000000..3712f8966dc584eba38a1612114f76c3f9cb6133
--- /dev/null
+++ b/kernel-4.4/drivers/spi/wk2xxx_spi.c
@@ -0,0 +1,1862 @@
+/*
+*   FILE NAME  : wk2xxx_spi.c   
+*
+*   WKIC Ltd.
+*   By  Xu XunWei Tech  
+*   DEMO Version :2.1 Data:2019-10-28
+*
+*   DESCRIPTION: Implements an interface for the wk2xxx of spi interface
+*
+*   1. compiler warnings all changes
+*/
+
+
+
+
+#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/tty.h>
+#include <linux/tty_flip.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/of_gpio.h>
+#include <linux/gpio.h>
+
+
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+//#include <asm/mach/map.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+//#include <linux/platform_data/spi-rockchip.h>
+#include "wk2xxx.h"
+
+
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+//#define _DEBUG_WK_FUNCTION
+//#define _DEBUG_WK_RX
+//#define _DEBUG_WK_TX
+//#define _DEBUG_WK_IRQ
+//#define _DEBUG_WK_VALUE
+//#define _DEBUG_WK_FIFO
+//#define _DEBUG_WK_TEST
+
+#define WK_RS485_FUNCTION
+#define WK_FIFO_FUNCTION
+
+#define WK2XXX_STATUS_PE    0x10
+#define WK2XXX_STATUS_FE    0x20
+#define WK2XXX_STATUS_BRK   0x40
+#define WK2XXX_STATUS_OE    0x80
+
+
+#define SPI_LEN_LIMIT       30     //MAX<=255
+
+
+static DEFINE_MUTEX(wk2xxxs_lock);                /* race on probe */
+static DEFINE_MUTEX(wk2xxxs_reg_lock);
+static DEFINE_MUTEX(wk2xxs_work_lock);                /* work on probe */
+static DEFINE_MUTEX(wk2xxxs_global_lock);
+void wk2xxx_reset(void);
+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_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;
+
+
+    uint8_t new_lcr;
+	uint8_t new_fwcr;
+    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 */
+int wkreset_gpio;
+/*
+* This function read wk2xxx of Global register:
+*/
+static int wk2xxx_read_global_reg(struct spi_device *spi,uint8_t reg,uint8_t *dat)
+{
+        struct spi_message msg;
+        uint8_t buf_wdat[2];
+        uint8_t buf_rdat[2];
+        int status;
+        struct spi_transfer index_xfer = {
+                .len            = 2,
+                //.cs_change      = 1,
+                .speed_hz	= wk2xxx_spi_speed,
+        };
+        mutex_lock(&wk2xxxs_reg_lock);
+        status =0;
+        spi_message_init(&msg);
+        buf_wdat[0] = 0x40|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);
+        mutex_unlock(&wk2xxxs_reg_lock);
+        if(status)
+        {
+         return status;
+         }
+        *dat = buf_rdat[1];
+         return 0;
+
+}
+/*
+* This function write wk2xxx of Global register:
+*/
+static int wk2xxx_write_global_reg(struct spi_device *spi,uint8_t reg,uint8_t dat)
+{
+        struct spi_message msg;
+        uint8_t buf_reg[2];
+        int status;
+        struct spi_transfer index_xfer = {
+                .len            = 2,
+                //.cs_change      = 1,
+                .speed_hz	= wk2xxx_spi_speed,
+        };
+        mutex_lock(&wk2xxxs_reg_lock);
+        spi_message_init(&msg);
+        /* register index */
+        buf_reg[0] = 0x00|reg;
+        buf_reg[1] = dat;
+        index_xfer.tx_buf = buf_reg;
+        spi_message_add_tail(&index_xfer, &msg);
+        status = spi_sync(spi, &msg);
+        mutex_unlock(&wk2xxxs_reg_lock);
+        return status;
+}
+/*
+* This function read wk2xxx of slave register:
+*/
+static int wk2xxx_read_slave_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;
+        struct spi_transfer index_xfer = {
+                .len            = 2,
+                //.cs_change      = 1,
+                .speed_hz	= wk2xxx_spi_speed,
+        };
+        mutex_lock(&wk2xxxs_reg_lock);
+        status =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);
+        mutex_unlock(&wk2xxxs_reg_lock);
+        if(status)
+        {
+           return status;
+         }
+        *dat = buf_rdat[1];
+         return 0;
+
+}
+/*
+* This function write wk2xxx of Slave register:
+*/
+static int wk2xxx_write_slave_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;
+        struct spi_transfer index_xfer = {
+                .len            = 2,
+                //.cs_change      = 1,
+				.speed_hz	= wk2xxx_spi_speed,
+        };
+        mutex_lock(&wk2xxxs_reg_lock);
+        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);
+        mutex_unlock(&wk2xxxs_reg_lock);
+        return status;
+}
+
+#define MAX_RFCOUNT_SIZE 256
+
+/*
+* This function read wk2xxx of fifo:
+*/
+static int wk2xxx_read_fifo(struct spi_device *spi,uint8_t port,uint8_t fifolen,uint8_t *dat)
+{
+        struct spi_message msg;
+        int status,i;
+        uint8_t recive_fifo_data[MAX_RFCOUNT_SIZE+1]={0};
+        uint8_t transmit_fifo_data[MAX_RFCOUNT_SIZE+1]={0};
+        struct spi_transfer index_xfer = {
+                .len            = fifolen+1,
+                //.cs_change      = 1,
+                .speed_hz	= wk2xxx_spi_speed,
+        }; 
+	    if(!(fifolen>0))
+	      {
+			printk(KERN_ERR "%s,fifolen error!!\n", __func__);
+			return 1;
+		  }
+        mutex_lock(&wk2xxxs_reg_lock);
+        spi_message_init(&msg);
+        /* register index */
+        transmit_fifo_data[0] = ((port-1)<<4)|0xc0;
+        index_xfer.tx_buf = transmit_fifo_data;
+        index_xfer.rx_buf =(void *) recive_fifo_data;
+        spi_message_add_tail(&index_xfer, &msg);
+        
+        status = spi_sync(spi, &msg);
+        udelay(1);
+        for(i=0;i<fifolen;i++)
+            *(dat+i)=recive_fifo_data[i+1];
+        mutex_unlock(&wk2xxxs_reg_lock);
+		printk(KERN_ALERT "%s!!status=%d!---\n", __func__,status);
+        return status;
+        
+}
+/*
+* This function write wk2xxx of fifo:
+*/
+static int wk2xxx_write_fifo(struct spi_device *spi,uint8_t port,uint8_t fifolen,uint8_t *dat)
+{
+        struct spi_message msg;
+        int status,i;
+        uint8_t recive_fifo_data[MAX_RFCOUNT_SIZE+1]={0};
+        uint8_t transmit_fifo_data[MAX_RFCOUNT_SIZE+1]={0};
+        struct spi_transfer index_xfer = {
+                .len            = fifolen+1,
+                //.cs_change      = 1,
+                .speed_hz	= wk2xxx_spi_speed,
+        }; 
+	    if(!(fifolen>0))
+	      {
+			printk(KERN_ERR "%s,fifolen error,fifolen:%d!!\n", __func__,fifolen);
+			return 1;
+		  }
+
+        mutex_lock(&wk2xxxs_reg_lock);
+        spi_message_init(&msg);
+        /* register index */
+        transmit_fifo_data[0] = ((port-1)<<4)|0x80;
+         for(i=0;i<fifolen;i++)
+            {
+            transmit_fifo_data[i+1]=*(dat+i);
+            }
+        index_xfer.tx_buf = transmit_fifo_data;
+        index_xfer.rx_buf =(void *) recive_fifo_data;
+        spi_message_add_tail(&index_xfer, &msg);
+        status = spi_sync(spi, &msg);
+        mutex_unlock(&wk2xxxs_reg_lock);
+		printk( KERN_ALERT "%s!!status=%d!---\n", __func__,status);
+        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_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+	#endif
+
+    if (!s->force_end_work && !work_pending(&s->work) && !freezing(current) && !s->suspending)
+    {
+        queue_work(s->workqueue, &s->work);//
+		#ifdef _DEBUG_WK_FUNCTION
+        printk( "%s!!--queue_work---ok!---\n", __func__);
+        //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_WK_FUNCTION
+      printk( "%s!!--queue_work---error!---\n", __func__);
+      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
+
+//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)
+{  
+
+
+    struct wk2xxx_port *s = container_of(w, struct wk2xxx_port, work);
+    uint8_t rx;
+
+        
+
+    int work_start_tx_flag; 
+    int work_stop_rx_flag;
+    int work_irq_flag;
+    int work_conf_flag;
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+#endif
+    do {
+
+             mutex_lock(&wk2xxs_work_lock);
+     
+             work_start_tx_flag = s->start_tx_flag;
+             if(work_start_tx_flag)
+             s->start_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;
+             mutex_unlock(&wk2xxs_work_lock);
+         
+             if(work_start_tx_flag)
+             {
+              wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
+              rx |= WK2XXX_TFTRIG_IEN|WK2XXX_RFTRIG_IEN|WK2XXX_RXOUT_IEN; 
+              wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
+             }
+     
+             if(work_stop_rx_flag)
+             {
+              wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
+              rx &=~WK2XXX_RFTRIG_IEN;
+              rx &=~WK2XXX_RXOUT_IEN;
+              wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
+             }
+     
+             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 ));
+
+
+        if(s->start_tx_fail)
+        {
+            wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
+            rx |= WK2XXX_TFTRIG_IEN|WK2XXX_RFTRIG_IEN|WK2XXX_RXOUT_IEN;
+            wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
+        	s->start_tx_fail =0;
+
+        }
+        
+        
+       if(s->stop_rx_fail)
+        {
+            wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
+            rx &=~WK2XXX_RFTRIG_IEN;
+            rx &=~WK2XXX_RXOUT_IEN;
+            wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
+            s->stop_rx_fail =0;
+        }
+        if(s->irq_fail)
+        {
+            s->irq_fail = 0;
+            enable_irq(s->port.irq);
+        }
+
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+
+}
+
+
+static void wk2xxx_rx_chars(struct uart_port *port)
+{
+
+
+    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+    uint8_t fsr,lsr,dat[1],rx_dat[256]={0};
+    unsigned int ch,flg,sifr, ignored=0,status = 0,rx_count=0;
+    int rfcnt=0,rfcnt2=0,rx_num=0;
+	int len_rfcnt,len_limit,len_p=0;
+	len_limit=SPI_LEN_LIMIT;
+#ifdef _DEBUG_WK_FUNCTION
+		printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+#endif
+
+    wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
+    wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
+    fsr = dat[0];
+    wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_LSR,dat);
+    lsr = dat[0];
+    wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
+    sifr=dat[0];
+#ifdef _DEBUG_WK_RX
+     printk(KERN_ALERT "rx_chars()-port:%lx--fsr:0x%x--lsr:0x%x--\n",s->port.iobase,fsr,lsr);
+#endif
+if(!(sifr&0x80))//no error
+{  
+
+
+  flg = TTY_NORMAL;
+  if (fsr& WK2XXX_RDAT)
+  {
+    wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_RFCNT,dat);
+    rfcnt=dat[0];
+		wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_RFCNT,dat);
+    rfcnt2=dat[0];
+		if(!(rfcnt2>=rfcnt))
+		{
+			rfcnt=rfcnt2;
+		}
+	rfcnt=(rfcnt==0)?256:rfcnt;	
+#ifdef  _DEBUG_WK_RX
+      printk(KERN_ALERT "rx_chars()--port:%ld--rfcnt:0x%x-\n",s->port.iobase,rfcnt);
+#endif
+
+#ifdef WK_FIFO_FUNCTION  
+    //wk2xxx_read_fifo(s->spi_wk,s->port.iobase, rfcnt,rx_dat);
+	len_rfcnt=rfcnt;
+	while(len_rfcnt)
+		{
+			if(len_rfcnt>len_limit)
+				{
+					wk2xxx_read_fifo(s->spi_wk,s->port.iobase,len_limit,rx_dat+len_p);
+					len_rfcnt=len_rfcnt-len_limit;
+					len_p=len_p+len_limit;
+				}
+			else
+				{
+					wk2xxx_read_fifo(s->spi_wk,s->port.iobase,len_rfcnt,rx_dat+len_p);//
+					len_rfcnt=0;
+				}
+	  }
+
+
+#else
+	  for(rx_num=0;rx_num<rfcnt;rx_num++)
+		 {
+		   wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,dat);
+		   rx_dat[rx_num]=dat[0];
+		 }
+#endif
+
+    s->port.icount.rx+=rfcnt;
+        for(rx_num=0;rx_num<rfcnt;rx_num++)
+    {
+        if (uart_handle_sysrq_char(&s->port,rx_dat[rx_num]))//.state, ch))
+               break;//
+               
+#ifdef _DEBUG_WK_RX
+        printk(KERN_ALERT "rx_chars:0x%x----\n",rx_dat[rx_num]);
+#endif
+                  uart_insert_char(&s->port, status, WK2XXX_STATUS_OE, rx_dat[rx_num], flg);
+                  rx_count++;
+ 
+                  if ((rx_count >= 64 ) && (s->port.state->port.tty->port != NULL))
+                  {
+                   tty_flip_buffer_push(s->port.state->port.tty->port);
+                   rx_count = 0;
+                 }
+
+    }//for
+       if((rx_count > 0)&&(s->port.state->port.tty->port!= NULL))
+  {
+  		#ifdef _DEBUG_WK_RX
+          printk(KERN_ALERT  "push buffer tty flip port = :%lx count =:%d\n",s->port.iobase,rx_count);
+  		#endif
+         tty_flip_buffer_push(s->port.state->port.tty->port);
+         rx_count = 0;
+  }
+
+  }
+}//ifm
+else//error
+{
+    while (fsr& WK2XXX_RDAT)/**/
+        {
+            wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,dat);
+        ch = (int)dat[0];
+
+#ifdef _DEBUG_WK_RX
+
+        printk(KERN_ALERT "wk2xxx_rx_chars()----port:%lx--RXDAT:0x%x----\n",s->port.iobase,ch);
+#endif
+
+        s->port.icount.rx++;
+        //rx_count++;
+#ifdef _DEBUG_WK_RX
+            printk(KERN_ALERT "wk2xxx_rx_chars()----port:%lx error\n",s->port.iobase);
+#endif
+            flg = TTY_NORMAL;
+        if (lsr&(WK2XXX_OE |WK2XXX_FE|WK2XXX_PE|WK2XXX_BI))
+                {
+               printk(KERN_ALERT "wk2xxx_rx_chars()----port:%lx error,lsr:%x!!!!!!!!!!!!!!!!!\n",s->port.iobase,lsr);
+                        //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 >= 64 ) && (s->port.state->port.tty->port != NULL)) 
+        {
+         tty_flip_buffer_push(s->port.state->port.tty->port);
+         rx_count = 0;
+        } 
+#ifdef _DEBUG_WK_RX
+        printk(KERN_ALERT  " s->port.icount.rx = 0x%x char = 0x%x flg = 0x%X port = %lx rx_count = %d\n",s->port.icount.rx,ch,flg,s->port.iobase,rx_count);
+#endif
+        ignore_char:
+
+            wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
+            fsr = dat[0];
+            wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_LSR,dat);
+            lsr = dat[0];
+        }
+out:
+	if((rx_count > 0)&&(s->port.state->port.tty->port != NULL))
+{
+#ifdef _DEBUG_WK_FUNCTION
+        printk(KERN_ALERT  "push buffer tty flip port = :%lx count = :%d\n",s->port.iobase,rx_count);
+#endif
+        tty_flip_buffer_push(s->port.state->port.tty->port);
+        rx_count = 0;
+}
+
+}//if()else
+
+ #if 0
+   printk(KERN_ALERT  " rx_num = :%d\n",s->port.icount.rx);
+ #endif
+
+#ifdef _DEBUG_WK_FUNCTION
+	 printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+      	return;
+#ifdef SUPPORT_SYSRQ
+        s->port.state->sysrq = 0;
+#endif
+ 		goto error_return;
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+
+}
+
+static void wk2xxx_tx_chars(struct uart_port *port)
+{
+
+
+    	struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+    	uint8_t fsr,tfcnt,dat[1],txbuf[256]={0};
+    	int count,tx_count,i;
+		int len_tfcnt,len_limit,len_p=0;
+		len_limit=SPI_LEN_LIMIT;
+		#ifdef _DEBUG_WK_FUNCTION
+    	printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+		#endif
+        if (s->port.x_char) 
+        {   
+        #ifdef _DEBUG_WK_TX
+        printk(KERN_ALERT "wk2xxx_tx_chars   s->port.x_char:%x,port = %ld\n",s->port.x_char,s->port.iobase);
+       	#endif
+            wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,s->port.x_char);
+            s->port.icount.tx++;
+            s->port.x_char = 0;
+            goto out;
+        }
+
+        if(uart_circ_empty(&s->port.state->xmit) || uart_tx_stopped(&s->port))
+        {
+            goto out;
+
+        }
+
+    	wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
+    	fsr = dat[0];
+
+    	wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_TFCNT,dat); 
+    	tfcnt= dat[0];
+		#ifdef _DEBUG_WK_TX
+		printk(KERN_ALERT "wk2xxx_tx_chars   fsr:0x%x,tfcnt:0x%x,port = %ld\n",fsr,tfcnt,s->port.iobase);
+		#endif
+    	if(tfcnt==0)
+    	{
+	        tx_count=(fsr & WK2XXX_TFULL)?0:256;
+            #ifdef _DEBUG_WK_TX
+            printk(KERN_ALERT "wk2xxx_tx_chars2   tx_count:%x,port = %ld\n",tx_count,s->port.iobase);
+		    #endif
+    	}
+    	else
+    	{
+		    tx_count=256-tfcnt;
+		#ifdef _DEBUG_WK_TX
+        printk(KERN_ALERT "wk2xxx_tx_chars2   tx_count:%x,port = %ld\n",tx_count,s->port.iobase);
+		#endif 
+    	} 
+
+	count = tx_count;
+	i=0;
+	while(count)
+	{
+  		if(uart_circ_empty(&s->port.state->xmit))
+     			break;
+	   	txbuf[i]=s->port.state->xmit.buf[s->port.state->xmit.tail];
+	   	s->port.state->xmit.tail = (s->port.state->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
+	   	s->port.icount.tx++;
+	   	i++;
+		count=count-1;
+        #ifdef _DEBUG_WK_TX
+        printk(KERN_ALERT "tx_chars:0x%x--\n",txbuf[i-1]);
+        #endif
+   
+    };
+
+#ifdef WK_FIFO_FUNCTION 
+
+	//wk2xxx_write_fifo(s->spi_wk,s->port.iobase,i,txbuf);
+		len_tfcnt=i;    
+	while(len_tfcnt)
+		{
+			if(len_tfcnt>len_limit)
+				{
+                    
+
+					wk2xxx_write_fifo(s->spi_wk,s->port.iobase,len_limit,txbuf+len_p);	
+					len_p=len_p+len_limit;
+					len_tfcnt=len_tfcnt-len_limit;
+
+				}
+			else
+				{
+
+				    wk2xxx_write_fifo(s->spi_wk,s->port.iobase,len_tfcnt,txbuf+len_p);
+					len_p=len_p+len_tfcnt;
+					len_tfcnt=0;
+				}
+	   	}
+#else
+	for(count=0;count<i;count++)
+	{
+   		wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,txbuf[count]);	
+	}
+#endif
+
+
+	#ifdef _DEBUG_WK_VALUE
+	printk(KERN_ALERT "icount.tx:%d,xmit.head1:%d,xmit.tail:%d,UART_XMIT_SIZE::%lx,char:%x,fsr:0x%x,port = %ld\n",s->port.icount.tx,s->port.state->xmit.head,s->port.state->xmit.tail,UART_XMIT_SIZE,s->port.state->xmit.buf[s->port.state->xmit.tail],fsr,s->port.iobase);
+	#endif
+    	out:wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
+          fsr = dat[0];
+        if(((fsr&WK2XXX_TDAT)==0)&&((fsr&WK2XXX_TBUSY)==0))
+        {
+           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_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+
+
+}
+
+static irqreturn_t wk2xxx_irq(int irq, void *dev_id)//
+{
+        struct wk2xxx_port *s = dev_id;
+    	disable_irq_nosync(s->port.irq);
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+#endif       
+        s->irq_flag = 1;
+    	if(wk2xxx_dowork(s))
+    	{
+    	    ;
+    	}
+    	else
+    	{
+        	s->irq_flag = 0;
+        	s->irq_fail = 1;    
+    	}
+    
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+
+    	return IRQ_HANDLED;
+}
+
+static void wk2xxxirq_app(struct uart_port *port)//
+{
+    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+    unsigned int  pass_counter = 0;
+    uint8_t sifr,gifr,sier,dat[1];
+
+#ifdef _DEBUG_WK_IRQ
+    uint8_t gier,sifr0,sifr1,sifr2,sifr3,sier1,sier0,sier2,sier3;
+#endif
+
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+#endif
+
+    wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GIFR ,dat);
+    gifr = dat[0];
+
+#ifdef _DEBUG_WK_IRQ
+    wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GIER ,dat);
+    gier = dat[0];
+    wk2xxx_read_slave_reg(s->spi_wk,1,WK2XXX_SIFR,&sifr0);
+    wk2xxx_read_slave_reg(s->spi_wk,2,WK2XXX_SIFR,&sifr1);
+    wk2xxx_read_slave_reg(s->spi_wk,3,WK2XXX_SIFR,&sifr2);
+    wk2xxx_read_slave_reg(s->spi_wk,4,WK2XXX_SIFR,&sifr3);
+    wk2xxx_read_slave_reg(s->spi_wk,1,WK2XXX_SIER,&sier0);
+    wk2xxx_read_slave_reg(s->spi_wk,2,WK2XXX_SIER,&sier1);
+    wk2xxx_read_slave_reg(s->spi_wk,3,WK2XXX_SIER,&sier2);
+    wk2xxx_read_slave_reg(s->spi_wk,4,WK2XXX_SIER,&sier3);
+    printk(KERN_ALERT "irq_app....gifr:%x  gier:%x  sier1:%x  sier2:%x sier3:%x sier4:%x   sifr1:%x sifr2:%x sifr3:%x sifr4:%x \n",gifr,gier,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_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
+        sifr = dat[0];
+        wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
+        sier = dat[0];
+#ifdef _DEBUG_WK_IRQ
+        printk(KERN_ALERT "irq_app....port:%ld......sifr:%x sier:%x \n",s->port.iobase,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_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
+                sifr = dat[0];
+                wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
+                sier = dat[0];
+#ifdef _DEBUG_WK_VALUE
+    printk(KERN_ALERT "irq_app...........rx............tx  sifr:%x sier:%x port:%ld\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_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#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 tx;
+    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+#ifdef _DEBUG_WK_FUNCTION
+	printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+#endif
+	mutex_lock(&wk2xxxs_lock);
+	if(!(s->tx_empty_flag || s->tx_empty_fail))
+	{
+	    wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,&tx);
+	    while((tx & WK2XXX_TDAT)|(tx&WK2XXX_TBUSY))
+	   	{
+	   		wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,&tx);
+	   	}
+    	s->tx_empty = ((tx & WK2XXX_TDAT)|(tx&WK2XXX_TBUSY))<=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;
+		}
+	}
+	mutex_unlock(&wk2xxxs_lock);
+
+#ifdef _DEBUG_WK_VALUE
+       printk(KERN_ALERT "%s!!----FSR:%d--s->tx_empty:%d--\n",__func__,tx,s->tx_empty);
+#endif
+      
+#ifdef _DEBUG_WK_FUNCTION
+       printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+    	return s->tx_empty;
+
+
+}
+
+static void wk2xxx_set_mctrl(struct uart_port *port, u_int mctrl)//nothing
+{
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!---in--\n", __func__);
+#endif
+}
+static u_int wk2xxx_get_mctrl(struct uart_port *port)// since no modem control line
+{       
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!---in--\n", __func__);
+#endif
+        return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+}
+
+
+/*
+ *  interrupts disabled on entry
+ */
+
+static void wk2xxx_stop_tx(struct uart_port *port)//
+{
+
+    uint8_t dat[1],sier,sifr;
+	struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+	#endif
+
+    mutex_lock(&wk2xxxs_lock);
+	if(!(s->stop_tx_flag||s->stop_tx_fail))
+    {
+	    wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
+		sier=dat[0];
+		s->stop_tx_fail=(sier&WK2XXX_TFTRIG_IEN)>0;
+		if(s->stop_tx_fail)
+        {
+            wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
+            sier=dat[0];
+            sier&=~WK2XXX_TFTRIG_IEN;
+            wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,sier);
+			
+            wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
+            sifr=dat[0];
+            sifr&= ~WK2XXX_TFTRIG_INT;
+            wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,sifr);
+            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_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+	#endif
+  
+}
+
+/*
+ *  * interrupts may not be disabled on entry
+*/
+static void wk2xxx_start_tx(struct uart_port *port)
+{
+    
+		struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+	#endif
+       if(!(s->start_tx_flag||s->start_tx_fail))
+        {    
+				s->start_tx_flag = 1;
+            	if(wk2xxx_dowork(s))
+            	{
+                    ;
+            	}
+            	else
+            	{
+                    s->start_tx_fail = 1;
+					s->start_tx_flag = 0;
+            	}
+       	}
+         
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+	#endif
+
+
+
+}
+
+/*
+ *  * Interrupts enabled
+*/
+
+static void wk2xxx_stop_rx(struct uart_port *port)
+{
+        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+	#endif
+       	if(!(s->stop_rx_flag ||s->stop_rx_fail ))
+        {
+				s->stop_rx_flag = 1;
+            	if(wk2xxx_dowork(s))
+            	{
+                	;
+            	}
+            	else
+            	{
+                	s->stop_rx_flag = 0;
+                	s->stop_rx_fail = 1;
+            	}
+         }
+
+
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+	#endif
+
+
+}
+
+
+/*
+ *  * No modem control lines
+ *   */
+static void wk2xxx_enable_ms(struct uart_port *port)    //nothing
+{
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!---in--\n", __func__);
+	#endif
+
+
+}
+/*
+ *  * Interrupts always disabled.
+*/   
+static void wk2xxx_break_ctl(struct uart_port *port, int break_state)
+{
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!---in--\n", __func__);
+	#endif
+}
+
+
+static int wk2xxx_startup(struct uart_port *port)//i
+{
+
+        uint8_t gena,grst,gier,sier,scr,dat[1];
+        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+        char b[12];
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+	#endif
+        if (s->suspending)
+            return 0;   
+        s->force_end_work = 0;
+		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);
+        mutex_lock(&wk2xxxs_global_lock);  
+        wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GENA,dat);
+        gena=dat[0];
+        switch (s->port.iobase)
+        {
+          case 1:
+                  gena|=WK2XXX_UT1EN;
+                  wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GENA,gena);
+                  break;
+          case 2:
+                  gena|=WK2XXX_UT2EN;
+                  wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GENA,gena);
+                  break;
+          case 3:
+                 gena|=WK2XXX_UT3EN;
+                 wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GENA,gena);
+                  break;
+          case 4:
+                  gena|=WK2XXX_UT4EN;
+                  wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GENA,gena);
+                  break;
+          default:
+		          printk(KERN_ALERT ":con_wk2xxx_subport bad iobase %d\n", (uint8_t)s->port.iobase);
+                  break;
+        }
+ 
+        wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GRST,dat);
+        grst=dat[0];
+        switch (s->port.iobase)
+        {
+             case 1:
+                    grst|=WK2XXX_UT1RST;
+                    wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GRST,grst);
+                    break;
+             case 2:
+                    grst|=WK2XXX_UT2RST;
+                    wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GRST,grst);
+                    break;
+             case 3:
+                   grst|=WK2XXX_UT3RST;
+                   wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GRST,grst);
+                    break;
+             case 4:
+                    grst|=WK2XXX_UT4RST;
+                    wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GRST,grst);
+                    break;
+            default:
+     printk(KERN_ALERT ":con_wk2xxx_subport bad iobase %d\n", (uint8_t)s->port.iobase);
+                    break;
+        }
+
+		//enable the sub port interrupt
+		wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GIER,dat);
+		gier = dat[0];		
+		switch (s->port.iobase)
+			{
+				  case 1:
+						gier|=WK2XXX_UT1IE;
+						wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GIER,gier);
+						break;
+				  case 2:
+						gier|=WK2XXX_UT2IE;
+						wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GIER,gier);
+						break;
+				  case 3:
+						gier|=WK2XXX_UT3IE;
+						wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GIER,gier);
+						break;
+				  case 4:
+						gier|=WK2XXX_UT4IE;
+						wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GIER,gier);
+						break;
+				  default:
+						printk(KERN_ALERT ": bad iobase %d\n", (uint8_t)s->port.iobase);
+						break;
+			}
+
+
+		mutex_unlock(&wk2xxxs_global_lock);
+        
+        wk2xxx_read_slave_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_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,sier);
+
+        wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,dat);
+        scr = dat[0] | WK2XXX_TXEN|WK2XXX_RXEN;
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,scr);
+
+        //initiate the fifos
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FCR,0xff);//initiate the fifos
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FCR,0xfc);
+        //set rx/tx interrupt 
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE,1);  
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_RFTL,0x40);
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_TFTL,0X20);
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE,0);  
+		/*enable rs485*/
+		#ifdef WK_RS485_FUNCTION
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_RS485,0X02);//default  high
+		//wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_RS485,0X03);//default low
+		wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE,0X01);
+		wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_RRSDLY,0X10);
+		wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE,0X00);
+		#endif
+        /*****************************test**************************************/
+        #ifdef _DEBUG_WK_TEST
+        wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GENA,&gena);
+		wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GIER,&gier);
+		wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&sier);
+		wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,&scr);
+		wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FCR,dat);
+		printk(KERN_ALERT "%s!!-port:%ld;gena:0x%x;gier:0x%x;sier:0x%x;scr:0x%x;fcr:0x%x----\n", __func__,s->port.iobase,gena,gier,sier,scr,dat[0]);	
+		#endif
+		/**********************************************************************/
+        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, "wk2xxx_irq_gpio", s) < 0)
+        {
+                dev_warn(&s->spi_wk->dev, "cannot allocate irq %d\n", s->irq);
+                s->port.irq = 0;
+                destroy_workqueue(s->workqueue);
+                s->workqueue = NULL;
+                return -EBUSY;
+        }       udelay(100);
+        udelay(100);
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+
+       return 0;
+}
+//* Power down all displays on reboot, poweroff or halt *
+
+static void wk2xxx_shutdown(struct uart_port *port)
+{
+
+    uint8_t gena,dat[1];
+    struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+#endif
+    	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)
+    	{    
+          free_irq(s->port.irq, s);//閲婃斁涓柇
+    	}
+     	mutex_lock(&wk2xxxs_global_lock);
+     	wk2xxx_read_global_reg(s->spi_wk,WK2XXX_GENA,dat);
+        gena=dat[0];
+        switch (s->port.iobase)
+    	{
+        	case 1:
+                gena&=~WK2XXX_UT1EN;
+                wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GENA,gena);
+                break;
+          	case 2:
+                 gena&=~WK2XXX_UT2EN;
+                 wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GENA,gena);
+                 break;
+          	case 3:
+                 gena&=~WK2XXX_UT3EN;
+                 wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GENA,gena);
+                 break;
+          	case 4:
+                 gena&=~WK2XXX_UT4EN;
+                 wk2xxx_write_global_reg(s->spi_wk,WK2XXX_GENA,gena);
+                 break;
+          	default:
+                 printk(KERN_ALERT ":con_wk2xxx_subport bad iobase %d\n", (uint8_t)s->port.iobase);
+                 break;
+          }
+
+		mutex_unlock(&wk2xxxs_global_lock);
+
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+
+}
+
+static void conf_wk2xxx_subport(struct uart_port *port)//i
+{   
+
+
+	struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+	uint8_t old_sier,fwcr,lcr,scr,scr_ss,dat[1],baud0_ss,baud1_ss,pres_ss;
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+#endif
+	lcr = s->new_lcr;
+	scr_ss = s->new_scr;
+	baud0_ss=s->new_baud0;
+	baud1_ss=s->new_baud1;
+	pres_ss=s->new_pres;
+	fwcr=s->new_fwcr;
+	wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER ,dat);
+	old_sier = dat[0];
+	wk2xxx_write_slave_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_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
+	  } while (dat[0] & WK2XXX_TBUSY);
+        // then, disable tx and rx
+        wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,dat);
+        scr = dat[0];
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR ,scr&(~(WK2XXX_RXEN|WK2XXX_TXEN)));
+        // set the parity, stop bits and data size //
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_LCR ,lcr);
+		/*set cts  and rst*/
+		if(fwcr>0){  
+#ifdef _DEBUG_WK2XXX
+        printk(KERN_ALERT "-conf_wk2xxx_subport-set ctsrts--fwcr=0x%X\n",fwcr);
+#endif
+				wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FWCR,fwcr);
+				wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,1);
+				wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FWTH,0XF0);
+				wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_FWTL,0X80);
+				wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,0);
+		}
+    
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER ,old_sier);
+        // set the baud rate //
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,1);
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD0 ,baud0_ss);
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD1 ,baud1_ss);
+        wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_PRES ,pres_ss);
+	#ifdef _DEBUG_WK_FUNCTION
+         wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD0,dat);
+         printk(KERN_ALERT ":WK2XXX_BAUD0=0x%X\n", dat[0]);
+         wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD1,dat);
+         printk(KERN_ALERT ":WK2XXX_BAUD1=0x%X\n", dat[0]);
+         wk2xxx_read_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_PRES,dat);
+         printk(KERN_ALERT ":WK2XXX_PRES=0x%X\n", dat[0]);
+#endif
+         wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,0);
+         wk2xxx_write_slave_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR ,scr|(WK2XXX_RXEN|WK2XXX_TXEN));
+
+
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+#endif
+
+}
+
+
+// change speed
+static void wk2xxx_termios( struct uart_port *port, struct ktermios *termios,
+            struct ktermios *old)
+{
+
+	struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+	int baud = 0;
+	uint8_t lcr=0,fwcr,baud1,baud0,pres;
+	unsigned short cflag;
+	unsigned short lflag;
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--in--\n", __func__,s->port.iobase);
+	#endif
+	
+	cflag = termios->c_cflag;
+	lflag = termios->c_lflag;
+	#ifdef _DEBUG_WK_VALUE
+    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;
+			break;
+		case 230400:
+			baud1=0x00;
+			baud0=0x02;
+			pres=0;
+			break;
+		default:  
+			baud1=0x00;
+			baud0=0x00;
+			pres=0;
+			break;
+	}
+	tty_termios_encode_baud_rate(termios, baud, baud);
+
+	/* we are sending char from a workqueue so enable */
+
+
+	#ifdef _DEBUG_WK_VALUE
+    printk(KERN_ALERT "wk2xxx_termios()----port:%lx--lcr:0x%x- cflag:0x%x-CSTOPB:0x%x,PARENB:0x%x,PARODD:0x%x--\n",s->port.iobase,lcr,cflag,CSTOPB,PARENB,PARODD);
+	#endif
+
+        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_PAM1;
+                        lcr &= ~WK2XXX_PAM0;
+                }
+                else{
+                        lcr |= WK2XXX_PAM0;//PAM0=1
+                        lcr &= ~WK2XXX_PAM1;//PAM1=0
+                }
+        }
+        else{
+                lcr&=~WK2XXX_PAEN;
+        }
+
+		/*set rts and cts*/
+		fwcr=(termios->c_cflag&CRTSCTS)?0X30:0;
+		
+
+#ifdef _DEBUG_WK2XXX
+       printk(KERN_ALERT "wk2xxx_termios()----port:%ld--lcr:0x%x- cflag:0x%x-CSTOPB:0x%x,PARENB:0x%x,PARODD:0x%x--\n",s->port.iobase,lcr,cflag,CSTOPB,PARENB,PARODD);
+#endif
+
+	s->new_baud1=baud1;
+	s->new_baud0=baud0;	
+	s->new_pres=pres;
+	s->new_lcr = lcr;
+	s->new_fwcr = fwcr;
+
+#ifdef _DEBUG_WK2XXX
+       printk(KERN_ALERT "wk2xxx_termios()----port:%lx--NEW_FWCR-\n",s->port.iobase,s->new_fwcr);
+#endif
+
+	conf_wk2xxx_subport(&s->port);
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!-port:%ld;--exit--\n", __func__,s->port.iobase);
+	#endif
+}
+
+
+static const char *wk2xxx_type(struct uart_port *port)
+{
+
+
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!---in--\n", __func__);
+	#endif
+        return port->type == PORT_WK2XXX ? "wk2xxx" : NULL;//this is defined in serial_core.h
+}
+
+
+static void wk2xxx_release_port(struct uart_port *port)
+{
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!---in--\n", __func__);
+	#endif
+
+}
+
+
+static int wk2xxx_request_port(struct uart_port *port)//no such memory region needed for wk2xxx
+{
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!---in--\n", __func__);
+	#endif
+    return 0;
+}
+
+
+static void wk2xxx_config_port(struct uart_port *port, int flags)
+{
+        struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
+
+	#ifdef _DEBUG_WK_FUNCTION
+        printk(KERN_ALERT "%s!!\n", __func__);
+#endif
+
+        if (flags & UART_CONFIG_TYPE && wk2xxx_request_port(port) == 0)
+               s->port.type = PORT_WK2XXX;
+}
+
+
+static int wk2xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+
+        int ret = 0;
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!---in--\n", __func__);
+	#endif
+
+
+        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)
+        //      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
+};
+
+static int uart_driver_registered;
+static struct spi_driver wk2xxx_driver;
+
+/*
+ *瑙f瀽璁惧\E6\A0?
+ */
+//#ifdef CONFIG_OF
+static int wk2xxx_spi_parse_dt(struct device *dev)
+{
+
+	int irq_gpio, irq_flags, irq; 
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!--in--\n", __func__);
+	#endif
+
+	irq_gpio = of_get_named_gpio_flags(dev->of_node, "irq_gpio", 0,(enum of_gpio_flags *)&irq_flags);
+    	if (!gpio_is_valid(irq_gpio))
+    	{
+			printk(KERN_ERR"invalid wk2xxx_irq_gpio: %d\n", irq_gpio);
+			return -1;
+    	}
+   
+    	irq = gpio_to_irq(irq_gpio);
+    	if(!irq)
+    	{
+		printk(KERN_ERR"wk2xxx_irqGPIO: %d get irq failed!\n", irq);
+		//gpio_free(s->irq_gpio);
+		return -1;
+    	}
+	printk(KERN_ERR"wk2xxx_irq_gpio: %d, irq: %d", irq_gpio, irq);
+	wkreset_gpio = of_get_named_gpio(dev->of_node, "wkrst_gpio", 0);
+	if(gpio_request(wkreset_gpio, "wk_rest_gpio") < 0){
+		printk("requse wk rest gpio failed\n");
+	}
+	
+	wk2xxx_reset();
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!--exit--\n", __func__);
+	#endif
+	return irq;
+}
+
+void wk2xxx_reset(){
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!--in--\n", __func__);
+	#endif
+	gpio_direction_output(wkreset_gpio, 1);
+	msleep(10);
+	gpio_direction_output(wkreset_gpio, 0);
+	msleep(10);
+	gpio_direction_output(wkreset_gpio, 1);
+}
+
+static int wk2xxx_probe(struct spi_device *spi)
+{
+    	uint8_t i;
+	int time =2;
+    	int status, irq;
+    	uint8_t dat[1];
+#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!--in--\n", __func__);
+#endif
+	irq = wk2xxx_spi_parse_dt(&spi->dev);
+	if(irq<0)
+	{
+		return 1;
+	}
+	do
+	{
+		
+		wk2xxx_read_global_reg(spi,WK2XXX_GENA,dat);
+		printk(KERN_ERR "wk2xxx_probe()  GENA = 0x%X\n",dat[0]);//GENA=0X30
+		wk2xxx_write_global_reg(spi,WK2XXX_GENA,0xf5);
+		wk2xxx_read_global_reg(spi,WK2XXX_GENA,dat);
+		printk(KERN_ERR "wk2xxx_probe()  GENA = 0x%X\n",dat[0]);//GENA=0X35
+		wk2xxx_write_global_reg(spi,WK2XXX_GENA,0xf0);
+		wk2xxx_read_global_reg(spi,WK2XXX_GENA,dat);
+		printk(KERN_ERR "wk2xxx_probe()  GENA = 0x%X\n",dat[0]);//GENA=0X30
+		msleep(100);
+		time --;
+	}while(time > 0);
+/test spi //	
+
+	
+    	wk2xxx_read_global_reg(spi,WK2XXX_GENA,dat);
+    	if((dat[0]&0xf0)!=0x30)
+        { 
+          printk(KERN_ALERT "wk2xxx_probe()  GENA = 0x%X\n",dat[0]);
+          printk(KERN_ERR "spi driver  error!!!!\n");
+    //      return 1;
+        }
+    	mutex_lock(&wk2xxxs_lock);
+    	if(!uart_driver_registered)
+    	{
+        	    uart_driver_registered = 1;
+        	    status = uart_register_driver(&wk2xxx_uart_driver);
+        	if (status)
+        	{
+             	printk(KERN_ERR "Couldn't register wk2xxx uart driver\n");
+            	mutex_unlock(&wk2xxxs_lock);
+          //  	return status;
+        	}
+    	}
+        printk(KERN_ALERT "wk2xxx_serial_init.\n");
+
+    	for(i =0;i<NR_PORTS;i++)
+    	{
+        	    struct wk2xxx_port *s = &wk2xxxs[i];//container_of(port,struct wk2xxx_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      = irq;
+				s->port.iotype   = SERIAL_IO_PORT;
+				s->port.flags    = ASYNC_BOOT_AUTOCONF;
+		        status = uart_add_one_port(&wk2xxx_uart_driver, &s->port);
+       		if(status<0)
+          	{
+                  printk(KERN_ALERT "uart_add_one_port failed for line i:= %d with error %d\n",i,status);
+		          mutex_unlock(&wk2xxxs_lock);
+		          return status;
+           	}
+    	}
+        printk(KERN_ALERT "uart_add_one_port status= 0x%d\n",status);
+    	mutex_unlock(&wk2xxxs_lock);
+
+    	return status;
+}
+
+
+static int wk2xxx_remove(struct spi_device *spi)
+{
+
+    	int i;
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!--in--\n", __func__);
+	#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_ERR"removing wk2xxx driver\n");
+    	uart_unregister_driver(&wk2xxx_uart_driver);
+    	mutex_unlock(&wk2xxxs_lock);
+
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!--exit--\n", __func__);
+	#endif
+    	return 0;
+}
+#if 0
+static int wk2xxx_resume(struct spi_device *spi)
+{
+	#ifdef _DEBUG_WK_FUNCTION
+    printk(KERN_ALERT "%s!!--in--\n", __func__);
+	#endif
+    return 0;
+}
+#endif
+static const struct of_device_id mt_spi_wk2xxx_dt_match[] = {
+        { .compatible = "wkmic,wk2124spi_cs0", },
+		{ },
+};
+
+MODULE_DEVICE_TABLE(of, mt_spi_wk2xxx_dt_match);
+
+static struct spi_driver wk2xxx_driver = {
+        .driver = {
+                .name           = "wk2xxxspi",
+                .bus            = &spi_bus_type,
+                .owner          = THIS_MODULE,
+		.of_match_table = of_match_ptr(mt_spi_wk2xxx_dt_match),
+        },
+
+        .probe          = wk2xxx_probe,
+        .remove         = wk2xxx_remove,
+       // .resume         = wk2xxx_resume,
+};
+
+
+static int __init wk2xxx_init(void)
+{
+
+        int retval;
+        retval = spi_register_driver(&wk2xxx_driver);
+        printk(KERN_ALERT "%s,register spi return v = :%d\n",__func__,retval);
+        return retval;
+}
+
+
+
+static void __exit wk2xxx_exit(void)
+{
+
+      printk(KERN_ALERT "%s!!--in--\n", __func__);
+	  return spi_unregister_driver(&wk2xxx_driver);
+}
+
+
+module_init(wk2xxx_init);
+module_exit(wk2xxx_exit);
+
+MODULE_AUTHOR("WKMIC Ltd");
+MODULE_DESCRIPTION("wk2xxx generic serial port driver");
+MODULE_LICENSE("GPL");
+
+
+
+
+
+

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值