Android9.0 mtk SPI轉串列埠驅動除錯 wk2124
阿新 • • 發佈:2021-01-13
技術標籤:Android9.0android驅動程式kernel
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"); + + + + + +