IMX6下移植WKxxx驱动
wkXXX.c
#include<linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/console.h>
#include <linux/serial_core.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/freezer.h>
#include <linux/spi/spi.h>
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
//#include <mach/map.h>
#include <asm/irq.h>
#include <asm/io.h>
#include "wk2166.h"
/************硬件相关***************/
#include <mach/iomux-mx6q.h>
#define wk2166_irq IMX_GPIO_NR(7,6)// probe里做其他初始化
#define wk2166__cs IMX_GPIO_NR(5,29)//IMX_GPIO_NR(7,2)
MODULE_LICENSE("Dual BSD/GPL");
#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
//#define _DEBUG_WK2XXX
//#define _DEBUG_WK2XXX1
//#define _DEBUG_WK2XXX2
//#define _DEBUG_WK2XXX4
//#define _DEBUG_tla001
//#define _DEBUG_rx
#define CONFIG_DEVFS_FS
#define WK2XXX_PAGE1 1
#define WK2XXX_PAGE0 0
#define WK2XXX_STATUS_PE 1
#define WK2XXX_STATUS_FE 2
#define WK2XXX_STATUS_BRK 4
#define WK2XXX_STATUS_OE 8
static DEFINE_MUTEX(wk2xxxs_lock); /* race on probe */
static DEFINE_MUTEX(wk2xxs_work_lock); /* work on probe */
static DEFINE_MUTEX(wk2xxs_spi_lock); /* spi read & write */
struct wk2xxx_port
{
//struct timer_list mytimer;
struct uart_port port;//[NR_PORTS];
struct spi_device *spi_wk;
spinlock_t conf_lock; /* shared data */
struct workqueue_struct *workqueue;
struct work_struct work;
int suspending;
void (*wk2xxx_hw_suspend) (int suspend);
int tx_done;
int force_end_work;
int irq;
int minor; /* minor number */
int tx_empty;
int tx_empty_flag;
//int start_tx;
int start_tx_flag;
int stop_tx_flag;
int stop_rx_flag;
int irq_flag;
int conf_flag;
int tx_empty_fail;
int start_tx_fail;
int stop_tx_fail;
int stop_rx_fail;
int irq_fail;
int conf_fail;
/*
int work_tx_empty_flag;
int work_start_tx_flag;
int work_stop_rx_flag;
int work_stop_tx_flag;
int work_irq_flag;
//int work_irq_fail;
int work_conf_flag;
*/
uint8_t new_lcr;
uint8_t new_scr;
/*set baud 0f register*/
uint8_t new_baud1;
uint8_t new_baud0;
uint8_t new_pres;
};
static struct wk2xxx_port wk2xxxs[NR_PORTS]; /* the chips */
static int wk2xxx_read_reg(struct spi_device *spi,uint8_t port,uint8_t reg,uint8_t *dat)
{
struct spi_message msg;
uint8_t buf_wdat[2];
uint8_t buf_rdat[2];
int status;
mutex_lock(&wk2xxs_spi_lock);
struct spi_transfer index_xfer = {
.len = 2,
.cs_change = 1,
};
status =0;
__gpio_set_value(wk2166__cs,0);
spi_message_init(&msg);
buf_wdat[0] = 0x40|(((port-1)<<4)|reg);
buf_wdat[1] = 0x00;
buf_rdat[0] = 0x00;
buf_rdat[1] = 0x00;
index_xfer.tx_buf = buf_wdat;
index_xfer.rx_buf =(void *) buf_rdat;
spi_message_add_tail(&index_xfer, &msg);
status = spi_sync(spi, &msg);
udelay(5);
if(status)
{
return status;
}
*dat = buf_rdat[1];
__gpio_set_value(wk2166__cs,1);
mutex_unlock(&wk2xxs_spi_lock);
return 0;
}
static int wk2xxx_write_reg(struct spi_device *spi,uint8_t port,uint8_t reg,uint8_t dat)
{
struct spi_message msg;
uint8_t buf_reg[2];
int status;
mutex_lock(&wk2xxs_spi_lock);
struct spi_transfer index_xfer = {
.len = 2,
.cs_change = 1,
};
__gpio_set_value(wk2166__cs,0);
spi_message_init(&msg);
/* register index */
buf_reg[0] = ((port-1)<<4)|reg;
buf_reg[1] = dat;
index_xfer.tx_buf = buf_reg;
spi_message_add_tail(&index_xfer, &msg);
status = spi_sync(spi, &msg);
udelay(5);
if(status)
{
return status;
}
__gpio_set_value(wk2166__cs,1);
mutex_unlock(&wk2xxs_spi_lock);
return status;
}
static void wk2xxxirq_app(struct uart_port *port);//
static void conf_wk2xxx_subport(struct uart_port *port);//
static void wk2xxx_work(struct work_struct *w);
static void wk2xxx_stop_tx(struct uart_port *port);//
static u_int wk2xxx_tx_empty(struct uart_port *port);// or query the tx fifo is not empty?
static int wk2xxx_dowork(struct wk2xxx_port *s)
{
#ifdef _DEBUG_WK2XXX
printk("--wk2xxx_dowork---in---\n");
#endif
if (!s->force_end_work && !work_pending(&s->work) && !freezing(current) && !s->suspending)
{
queue_work(s->workqueue, &s->work);//
#ifdef _DEBUG_WK2XXX
printk("--queue_work---ok---\n");
printk("--wk2xxx_dowork---exit---\n");
// printk("work_pending =: %d s->force_end_work = : %d freezing(current) = :%d s->suspending= :%d\n" ,work_pending(&s->work),s->force_end_work ,freezing(current),s->suspending);
#endif
return 1;
}
else
{
#ifdef _DEBUG_WK2XXX
printk("--queue_work---error---\n");
printk("--wk2xxx_dowork---exit---\n");
#endif
//printk("work_pending =: %d s->force_end_work = : %d freezing(current) = :%d s->suspending= :%d\n" ,work_pending(&s->work),s->force_end_work ,freezing(current),s->suspending);
// return 0;
// printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s->irq_flag,s->tx_empty);
return 0;
}
}
static void wk2xxx_work(struct work_struct *w)
{
#ifdef _DEBUG_WK2XXX
printk("--wk2xxx_work---in---\n");
#endif
struct wk2xxx_port *s = container_of(w, struct wk2xxx_port, work);
uint8_t rx;
int work_tx_empty_flag;
int work_start_tx_flag;
int work_stop_rx_flag;
int work_stop_tx_flag;
int work_irq_flag;
//int work_irq_fail;
int work_conf_flag;
do {
mutex_lock(&wk2xxs_work_lock);
//spin_lock(&s->conf_lock);
/*work_tx_empty_flag = s->tx_empty_flag;
if(work_tx_empty_flag)
s->tx_empty_flag = 0;*/
work_start_tx_flag = s->start_tx_flag;
if(work_start_tx_flag)
s->start_tx_flag = 0;
/*work_stop_tx_flag = s->stop_tx_flag;
if(work_stop_tx_flag)
s->stop_tx_flag = 0;*/
work_stop_rx_flag = s->stop_rx_flag;
if(work_stop_rx_flag)
s->stop_rx_flag = 0;
work_conf_flag = s->conf_flag;
if(work_conf_flag)
s->conf_flag = 0;
work_irq_flag = s->irq_flag;
if(work_irq_flag)
s->irq_flag = 0;
//work_irq_fail = s->irq_fail;
//if(work_irq_fail)
//s->irq_fail = 0;
//spin_unlock(&s->conf_lock);
mutex_unlock(&wk2xxs_work_lock);
if(work_conf_flag)
{
conf_wk2xxx_subport(&s->port);
}
/*if(work_tx_empty_flag)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,&rx);
s->tx_empty = (rx & WK2XXX_TDAT)<=0;
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "s->tx_empty_fail----FSR:%d--s->tx_empty:%d--\n",rx,s->tx_empty);
#endif
}*/
if(work_start_tx_flag)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
rx |= WK2XXX_TFTRIG_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
}
/* if(work_stop_tx_flag)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
rx &=~WK2XXX_TFTRIG_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
rx &= ~WK2XXX_TFTRIG_INT;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
}*/
if(work_stop_rx_flag)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "stop_rx_flag----SIER:%d--\n",rx);
#endif
rx &=~WK2XXX_RFTRIG_IEN;
rx &=~WK2XXX_RXOUT_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "stop_rx_flag----SIFR:%d--\n",rx);
#endif
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
rx &= ~WK2XXX_RFTRIG_INT;
rx &= ~WK2XXX_RXOVT_INT;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "stop_rx_flag----SIFR:%d--\n",rx);
#endif
}
if(work_irq_flag)
{
wk2xxxirq_app(&s->port);
s->irq_fail = 1;
}
}while (!s->force_end_work && !freezing(current) && \
(work_irq_flag || work_stop_rx_flag || \
work_stop_tx_flag || work_tx_empty_flag || work_conf_flag));
/*
}while (!s->force_end_work && !freezing(current) && \
((s->work_irq_flag != s->irq_flag) ||\
(s->work_stop_rx_flag != s->stop_rx_flag) ||\
(s->work_stop_tx_flag != s->stop_tx_flag) ||\
(s->work_tx_empty_flag != s->tx_empty_flag) ||\
(s->work_conf_flag != s->conf_flag)));
*/
#ifdef _DEBUG_WK2XXX
printk("-----exit------- work ------\n");
#endif
if(s->conf_fail)
{
conf_wk2xxx_subport(&s->port);
s->conf_fail =0;
}
/*if(s->tx_empty_fail)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,&rx);
s->tx_empty = (rx & WK2XXX_TDAT) == 0;
s->tx_empty_fail =0;
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "s->tx_empty_fail----FSR:%d--s->tx_empty:%d--s->tx_empty_fail :%d--\n",rx,s->tx_empty,s->tx_empty_fail );
#endif
}*/
if(s->start_tx_fail)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
rx |= WK2XXX_TFTRIG_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
s->start_tx_fail =0;
}
/* if(s->stop_tx_fail)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
rx &=~WK2XXX_TFTRIG_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
rx &= ~WK2XXX_TFTRIG_INT;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
s->stop_tx_fail =0;
}*/
if(s->stop_rx_fail)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
rx &=~WK2XXX_RFTRIG_IEN;
rx &=~WK2XXX_RXOUT_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
rx &= ~WK2XXX_RFTRIG_INT;
rx &= ~WK2XXX_RXOVT_INT;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
s->stop_rx_fail =0;
}
if(s->irq_fail)
{
s->irq_fail = 0;
enable_irq(s->port.irq);
//s->irq_fail = 0;
}
//printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s-> irq_flag,s->tx_empty);
#ifdef _DEBUG_WK2XXX
printk("--wk2xxx_work---exit---\n");
#endif
//mutex_unlock(&wk2xxs_work_lock);
}
static void wk2xxx_rx_chars(struct uart_port *port)//vk32xx_port *port)
{
#ifdef _DEBUG_rx
printk(KERN_ALERT "wk2xxx_rx_chars()---------in---\n");
#endif
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
uint8_t fsr,lsr,dat[1];
unsigned int ch, flg, ignored=0,status = 0,rx_count=0;
#ifdef _DEBUG_tla001
int i;
for(i=1;i<5;i++)
{
wk2xxx_write_reg(s->spi_wk,i,WK2XXX_SPAGE,WK2XXX_PAGE0);
wk2xxx_read_reg(s->spi_wk,i,WK2XXX_GENA,dat);
printk(KERN_ALERT "Port%d WK2XXX_GENA****0x%x\n",i,dat[0]);
wk2xxx_read_reg(s->spi_wk,i,WK2XXX_SIER,dat);
printk(KERN_ALERT "Port%d WK2XXX_SIER****0x%x\n",i,dat[0]);
wk2xxx_read_reg(s->spi_wk,i,WK2XXX_SIFR,dat);
printk(KERN_ALERT "Port%d WK2XXX_SIFR****0x%x\n",i,dat[0]);
wk2xxx_write_reg(s->spi_wk,i,WK2XXX_SPAGE,WK2XXX_PAGE1);
wk2xxx_read_reg(s->spi_wk,i,WK2XXX_BAUD1,dat);
printk(KERN_ALERT "Port%d WK2XXX_BAUD1****0x%x\n",i,dat[0]);
wk2xxx_read_reg(s->spi_wk,i,WK2XXX_BAUD0,dat);
printk(KERN_ALERT "Port%d WK2XXX_BAUD0****0x%x\n",i,dat[0]);
wk2xxx_read_reg(s->spi_wk,i,WK2XXX_RFTL,dat);
printk(KERN_ALERT "Port%d WK2XXX_RFTL****0x%x\n",i,dat[0]);
wk2xxx_read_reg(s->spi_wk,i,WK2XXX_TFTL,dat);
printk(KERN_ALERT "Port%d WK2XXX_TFTL****0x%x\n\n",i,dat[0]);
}
#endif
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
fsr = dat[0];
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_LSR,dat);
lsr = dat[0];
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "wk2xxx_rx_chars()----port:%d--fsr:%d--lsr:%d--\n",s->port.iobase,fsr,lsr);
#endif
while (fsr& WK2XXX_RDAT)/**/
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,dat);
ch = (int)dat[0];
#ifdef _DEBUG_WK2XXX4
printk(KERN_ALERT "wk2xxx_rx_chars()----port:%d--RXDAT:0x%x----\n",s->port.iobase,ch);
#endif
s->port.icount.rx++;
//rx_count++;
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "icount.rx:%d\n",s->port.icount.rx);
#endif
flg = TTY_NORMAL;
if (lsr&(WK2XXX_OE |WK2XXX_FE|WK2XXX_PE|WK2XXX_BI))
{
printk(KERN_ALERT "all err\n");
//goto handle_error;
if (lsr & WK2XXX_PE)
{
s->port.icount.parity++;
status |= WK2XXX_STATUS_PE;
flg = TTY_PARITY;
}
if (lsr & WK2XXX_FE)
{
s->port.icount.frame++;
status |= WK2XXX_STATUS_FE;
flg = TTY_FRAME;
}
if (lsr & WK2XXX_OE)
{
s->port.icount.overrun++;
status |= WK2XXX_STATUS_OE;
flg = TTY_OVERRUN;
}
if(lsr&fsr & WK2XXX_BI)
{
s->port.icount.brk++;
status |= WK2XXX_STATUS_BRK;
flg = TTY_BREAK;
}
if (++ignored > 100)
goto out;
goto ignore_char;
}
error_return:
if (uart_handle_sysrq_char(&s->port,ch))//.state, ch))
goto ignore_char;
uart_insert_char(&s->port, status, WK2XXX_STATUS_OE, ch, flg);
rx_count++;
if ((rx_count >= 8 ) && (s->port.state->port.tty != NULL))
{
tty_flip_buffer_push(s->port.state->port.tty);
rx_count = 0;
}
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT " s->port.icount.rx = 0x%X char = 0x%X flg = 0x%X port = %d rx_count = %d\n",s->port.icount.rx,ch,flg,s->port.iobase,rx_count);
#endif
ignore_char:
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
fsr = dat[0];
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_LSR,dat);
lsr = dat[0];
}
out:
if((rx_count > 0)&&(s->port.state->port.tty != NULL))
{
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "push buffer tty flip port = :%d count = :%d\n",s->port.iobase,rx_count);
#endif
tty_flip_buffer_push(s->port.state->port.tty);
}
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "wk2xxx_rx_chars()---------out---\n");
#endif
return;
#ifdef SUPPORT_SYSRQ
s->port.state->sysrq = 0;
#endif
goto error_return;
#ifdef _DEBUG_rx
printk("--wk2xxx_rx_chars---exit---\n");
#endif
}
static void wk2xxx_tx_chars(struct uart_port *port)//
{
#ifdef _DEBUG_WK2XXX4
printk("--wk2xxx_tx_chars---in---\n");
#endif
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
uint8_t fsr,dat[1];
int count;
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT " in wk2xxx_tx_chars()\n");
#endif
if (s->port.x_char)
{
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,s->port.x_char);
s->port.icount.tx++;
s->port.x_char = 0;
goto out;
//return;
}
if(uart_circ_empty(&s->port.state->xmit) || uart_tx_stopped(&s->port))
{
//wk2xxx_stop_tx(&s->port);
goto out;
//return;
}
/*
* Tried using FIFO (not checking TNF) for fifo fill:
* still had the '1 bytes repeated' problem.
*/
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
fsr = dat[0];
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "fsr:%x\n",fsr);
#endif
//count = s->port.fifosize / 2;
count = s->port.fifosize;
//count = 64;
do
{
if((fsr & WK2XXX_TFULL)|uart_circ_empty(&s->port.state->xmit))
goto out;
// break;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_FDAT,s->port.state->xmit.buf[s->port.state->xmit.tail]);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "wk2xxx_tx_chars()----port:%d--TXDAT:0x%x----\n",s->port.iobase,s->port.state->xmit.buf[s->port.state->xmit.tail]);
#endif
//udelay(1000);
s->port.state->xmit.tail = (s->port.state->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
s->port.icount.tx++;
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "xmit.head:%d,xmit.tail:%d,char:%d,fsr:0x%X,port = %d\n",s->port.state->xmit.head,s->port.state->xmit.tail,s->port.state->xmit.buf[s->port.state->xmit.tail],fsr,s->port.iobase);
#endif
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
fsr = dat[0];
}while(--count>0);
#ifdef _DEBUG_WK2XXX
do
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
fsr = dat[0];
}while(fsr&WK2XXX_TDAT>0);
printk(KERN_ALERT "tx_char --fsr:0x%X,port = %d\n",fsr,s->port.iobase);
#endif
out:wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
fsr = dat[0];
//printk(KERN_ALERT "tx_char --fsr:0x%X,port = %d\n",fsr,s->port.iobase);
if((fsr&WK2XXX_TDAT)==0)
{
//printk(KERN_ALERT "tx_char1 --fsr:0x%X,port = %d\n",fsr,s->port.iobase);
if (uart_circ_chars_pending(&s->port.state->xmit) < WAKEUP_CHARS)
uart_write_wakeup(&s->port);
if (uart_circ_empty(&s->port.state->xmit))
{
wk2xxx_stop_tx(&s->port);
}
}
#ifdef _DEBUG_WK2XXX
printk("--wk2xxx_tx_chars---exit---\n");
#endif
}
static irqreturn_t wk2xxx_irq(int irq, void *dev_id)//
{
#ifdef _DEBUG_WK2XXX
printk("--wk2xxx_irq---in---\n");
#endif
struct wk2xxx_port *s = dev_id;
//char sier;
disable_irq_nosync(s->port.irq);
//s->irq_fail=1;
//s->irq_flag = 1;
//mutex_unlock(&vk32xxs_work_lock);
//vk32xx_dowork(s);
if(wk2xxx_dowork(s))
{
//disable_irq_nosync(s->port.irq);
//if(!s->irq_fail)
//{
s->irq_flag = 1;
#ifdef _DEBUG_tla00
printk(KERN_ALERT "****** irq_flag=1*****\n");
#endif
//s->irq_fail = 0;
//}
}
else
{
//if(!s->irq_flag)
s->irq_fail = 1;
#ifdef _DEBUG_tla001
printk(KERN_ALERT "****** irq_fail=1*****\n");
#endif
}
//disable_irq_nosysc(s->port.irq);
#ifdef _DEBUG_WK2XXX
printk("--wk2xxx_irq---exit---\n");
#endif
return IRQ_HANDLED;
}
static void wk2xxxirq_app(struct uart_port *port)//
{
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "wk2xxxirq_app()------port:%d--------------\n",s->port.iobase);
#endif
unsigned int pass_counter = 0;
uint8_t sifr,gifr,sier,dat[1];
uint8_t sifr0,sifr1,sifr2,sifr3,sier1,sier0,sier2,sier3;
wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIFR ,dat);
gifr = dat[0];
wk2xxx_write_reg(s->spi_wk,1,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
wk2xxx_write_reg(s->spi_wk,2,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
wk2xxx_write_reg(s->spi_wk,3,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
wk2xxx_write_reg(s->spi_wk,4,WK2XXX_SPAGE,WK2XXX_PAGE0);//set register in page0
wk2xxx_read_reg(s->spi_wk,1,WK2XXX_SIFR,&sifr0);
wk2xxx_read_reg(s->spi_wk,2,WK2XXX_SIFR,&sifr1);
wk2xxx_read_reg(s->spi_wk,3,WK2XXX_SIFR,&sifr2);
wk2xxx_read_reg(s->spi_wk,4,WK2XXX_SIFR,&sifr3);
wk2xxx_read_reg(s->spi_wk,1,WK2XXX_SIER,&sier0);
wk2xxx_read_reg(s->spi_wk,2,WK2XXX_SIER,&sier1);
wk2xxx_read_reg(s->spi_wk,3,WK2XXX_SIER,&sier2);
wk2xxx_read_reg(s->spi_wk,4,WK2XXX_SIER,&sier3);
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "irq_app....gifr:%x sier1:%x sier2:%x sier3:%x sier4:%x sifr1:%x sifr2:%x sifr3:%x sifr4:%x \n",gifr,sier0,sier1,sier2,sier3,sifr0,sifr1,sifr2,sifr3);
#endif
switch(s->port.iobase)
{
case 1 :
if(!(gifr & WK2XXX_UT1INT))
{
return;
}
break;
case 2 :
if(!(gifr & WK2XXX_UT2INT))
{
return;
}
break;
case 3 :
if(!(gifr & WK2XXX_UT3INT))
{
return;
}
break;
case 4 :
if(!(gifr & WK2XXX_UT4INT))
{
return;
}
break;
default:
break;
}
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
sifr = dat[0];
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
sier = dat[0];
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "irq_app..........sifr:%x sier:%x \n",sifr,sier);
#endif
do {
if ((sifr&WK2XXX_RFTRIG_INT)||(sifr&WK2XXX_RXOVT_INT))
{
wk2xxx_rx_chars(&s->port);
}
if ((sifr & WK2XXX_TFTRIG_INT)&&(sier & WK2XXX_TFTRIG_IEN ))
{
wk2xxx_tx_chars(&s->port);
return;
}
if (pass_counter++ > WK2XXX_ISR_PASS_LIMIT)
break;
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,dat);
sifr = dat[0];
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
sier = dat[0];
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "irq_app...........rx............tx sifr:%x sier:%x port:%x\n",sifr,sier,s->port.iobase);
#endif
} while ((sifr&WK2XXX_RXOVT_INT)||(sifr & WK2XXX_RFTRIG_INT)||((sifr & WK2XXX_TFTRIG_INT)&&(sier & WK2XXX_TFTRIG_IEN)));
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "sifr:%d\n",sifr);
#endif
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "wk2xxxirq_app()---------exit---\n");
#endif
}
/*
* Return TIOCSER_TEMT when transmitter is not busy.
*/
static u_int wk2xxx_tx_empty(struct uart_port *port)// or query the tx fifo is not empty?
{
uint8_t rx;
mutex_lock(&wk2xxxs_lock);
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "wk2xxx_tx_empty()---------in---\n");
#endif
// mutex_lock(&wk2xxxs_lock);
//s->tx_empty_flag = 1;
/*if(!(s->tx_empty_flag || s->tx_empty_fail))
{
if(wk2xxx_dowork(s))
{
s->tx_empty_flag = 1;
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "tx_empty_flag=1");
#endif
}
else
{
#ifdef _DEBUG_WK2XXX1
printk(KERN_ALERT "tx_empty_fail=1");
#endif
s->tx_empty_fail = 1;
}
}*/
if(!(s->tx_empty_flag || s->tx_empty_fail))
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,&rx);
s->tx_empty = (rx & WK2XXX_TDAT)<=0;
if(s->tx_empty)
{
s->tx_empty_flag =0;
s->tx_empty_fail=0;
}
else
{
s->tx_empty_fail=0;
s->tx_empty_flag =0;
}
}
#ifdef _DEBUG_WK2XXX4
printk(KERN_ALERT "s->tx_empty_fail----FSR:%d--s->tx_empty:%d--\n",rx,s->tx_empty);
#endif
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "wk2xxx_tx_empty----------exit---\n");
#endif
mutex_unlock(&wk2xxxs_lock);
return s->tx_empty;
}
static void wk2xxx_set_mctrl(struct uart_port *port, u_int mctrl)//nothing
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_set_mctrl---------exit---\n");
#endif
}
static u_int wk2xxx_get_mctrl(struct uart_port *port)// since no modem control line
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_get_mctrl---------exit---\n");
#endif
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
}
/*
* interrupts disabled on entry
*/
static void wk2xxx_stop_tx(struct uart_port *port)//
{
mutex_lock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_stop_tx------in---\n");
#endif
uint8_t rx;
//mutex_lock(&wk2xxxs_lock);
//disable the interrupt,clear the corresponding bit in GIR
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
//s->stop_tx_flag = 1;
/* if(!(s->stop_tx_flag||s->stop_tx_fail))
{
if(wk2xxx_dowork(s))
{
s->stop_tx_flag =1;
}
else
{
s->stop_tx_fail =1;
}
}*/
if(!(s->stop_tx_flag||s->stop_tx_fail))
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
s->stop_tx_fail=rx&WK2XXX_TFTRIG_IEN>0;
if(s->stop_tx_fail)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
rx &=~WK2XXX_TFTRIG_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
rx &= ~WK2XXX_TFTRIG_INT;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
s->stop_tx_fail =0;
s->stop_tx_flag=0;
}
else
{
s->stop_tx_fail =0;
s->stop_tx_flag=0;
}
}
//mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX4
printk(KERN_ALERT "-wk2xxx_stop_tx------exit---\n");
#endif
mutex_unlock(&wk2xxxs_lock);
}
/*
* * interrupts may not be disabled on entry
*/
static void wk2xxx_start_tx(struct uart_port *port)
{
//mutex_lock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_start_tx------in---\n");
#endif
// mutex_lock(&wk2xxxs_lock);
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
// uint8_t rx;
//s->start_tx_flag = 1;
//vk32xx_dowork(s);
if(!(s->start_tx_flag||s->start_tx_fail))
{
if(wk2xxx_dowork(s))
{
s->start_tx_flag = 1;
#ifdef _DEBUG_tla001
printk(KERN_ALERT "****** start_tx_flag=1*****\n");
#endif
}
else
{
s->start_tx_fail = 1;
#ifdef _DEBUG_tla001
printk(KERN_ALERT "****** start_tx_fail=1*****\n");
#endif
}
}
// mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_start_tx------exit---\n");
#endif
// mutex_unlock(&wk2xxxs_lock);
// vk32xx_read_reg(s->spi_vk,s->port.iobase,VK32XX_SIER,&rx);
// rx |= VK32XX_TRIEN;
// vk32xx_write_reg(s->spi_vk,s->port.iobase,VK32XX_SIER,rx);
}
/*
* * Interrupts enabled
*/
static void wk2xxx_stop_rx(struct uart_port *port)
{
//mutex_lock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_stop_rx------in---\n");
#endif
// uint8_t rx;
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
//s->stop_rx_flag = 1;
// mutex_lock(&wk2xxxs_lock);
if(!(s->stop_rx_flag ||s->stop_rx_fail ))
{
if(wk2xxx_dowork(s))
{
s->stop_rx_flag = 1;
#ifdef _DEBUG_tla001
printk(KERN_ALERT "****** stop_rx_flag=1*****\n");
#endif
}
else
{
s->stop_rx_fail = 1;
#ifdef _DEBUG_tla001
printk(KERN_ALERT "****** stop_rx_fail=1*****\n");
#endif
}
}
/*
if(!(s->stop_rx_flag ||s->stop_rx_fail ))
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
s->stop_rx_fail=rx&WK2XXX_RFTRIG_IEN||rx&WK2XXX_RXOUT_IEN>0;
if(s->stop_rx_fail)
{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,&rx);
rx &=~WK2XXX_RFTRIG_IEN;
rx &=~WK2XXX_RXOUT_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,rx);
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,&rx);
rx &= ~WK2XXX_RFTRIG_INT;
rx &= ~WK2XXX_RXOVT_INT;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIFR,rx);
s->stop_rx_fail =0;
s->stop_rx_flag = 0;
}
else
{
s->stop_rx_fail =0;
s->stop_rx_flag = 0;
}
}*/
// mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_stop_rx------exit---\n");
#endif
//mutex_unlock(&wk2xxxs_lock);
}
/*
* * No modem control lines
* */
static void wk2xxx_enable_ms(struct uart_port *port) //nothing
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_enable_ms------exit---\n");
#endif
}
/*
* * Interrupts always disabled.
*/
static void wk2xxx_break_ctl(struct uart_port *port, int break_state)
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_break_ctl------exit---\n");
#endif
//break operation, but there seems no such operation in vk32
}
static int wk2xxx_startup(struct uart_port *port)//i
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_startup------in---\n");
#endif
uint8_t gena,grst,gier,sier,scr,dat[1];
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
char b[12];
if (s->suspending)
return 0;
//printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s-> irq_flag,s->tx_empty);
s->force_end_work = 0;
sprintf(b, "wk2xxx-%d", (uint8_t)s->port.iobase);
//s->workqueue = create_singlethread_workqueue(b);
s->workqueue = create_workqueue(b);
if (!s->workqueue)
{
dev_warn(&s->spi_wk->dev, "cannot create workqueue\n");
return -EBUSY;
}
INIT_WORK(&s->work, wk2xxx_work);
if (s->wk2xxx_hw_suspend)
s->wk2xxx_hw_suspend(0);
//wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,0);
wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,dat);//默认0x30
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******read WK2XXX_GENA*****0x%x\n",dat[0]);
#endif
gena=dat[0];
switch (s->port.iobase)
{
case 1:
gena|=WK2XXX_UT1EN;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,gena);
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******wk1 write WK2XXX_GENA*****0x%x\n",gena);
#endif
break;
case 2:
gena|=WK2XXX_UT2EN;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,gena);
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******wk2 write WK2XXX_GENA*****0x%x\n",gena);
#endif
break;
case 3:
gena|=WK2XXX_UT3EN;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,gena);
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******wk3 write WK2XXX_GENA*****0x%x\n",gena);
#endif
break;
case 4:
gena|=WK2XXX_UT4EN;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,gena);
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******wk4 write WK2XXX_GENA*****0x%x\n",gena);
#endif
break;
default:
printk(KERN_ALERT ":con_wk2xxx_subport bad iobase %d\n", (uint8_t)s->port.iobase);
}
wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,dat);
grst=dat[0];
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******read WK2XXX_GRST*****0x%x\n",grst);
#endif
switch (s->port.iobase)
{
case 1:
grst|=WK2XXX_UT1RST;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,grst);
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******wk1 write WK2XXX_GRST*****0x%x\n",grst);
#endif
break;
case 2:
grst|=WK2XXX_UT2RST;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,grst);
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******wk2 write WK2XXX_GRST*****0x%x\n",grst);
#endif
break;
case 3:
grst|=WK2XXX_UT3RST;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,grst);
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******wk3 write WK2XXX_GRST*****0x%x\n",grst);
#endif
break;
case 4:
grst|=WK2XXX_UT4RST;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GRST,grst);
#ifdef _DEBUG_tla001
printk(KERN_ALERT "******wk4 write WK2XXX_GRST*****0x%x\n",grst);
#endif
break;
default:
printk(KERN_ALERT ":con_wk2xxx_subport bad iobase %d\n", (uint8_t)s->port.iobase);
}
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,dat);
sier = dat[0];
sier &= ~WK2XXX_TFTRIG_IEN;
sier |= WK2XXX_RFTRIG_IEN;
sier |= WK2XXX_RXOUT_IEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER,sier);
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,dat);
scr = dat[0] | WK2XXX_TXEN|WK2XXX_RXEN;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,scr);
//initiate the fifos
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_FCR,0x0f);//initiate the fifos
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_FCR,0x0c);
//enable the sub port interrupt
wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,dat);
gier = dat[0];
switch (s->port.iobase){
case 1:
gier|=WK2XXX_UT1IE;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,gier);
break;
case 2:
gier|=WK2XXX_UT2IE;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,gier);
break;
case 3:
gier|=WK2XXX_UT3IE;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,gier);
break;
case 4:
gier|=WK2XXX_UT4IE;
wk2xxx_write_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GIER,gier);
break;
default:
printk(KERN_ALERT ": bad iobase %d\n", (uint8_t)s->port.iobase);
}
if (s->wk2xxx_hw_suspend)
s->wk2xxx_hw_suspend(0);
msleep(50);
uart_circ_clear(&s->port.state->xmit);
wk2xxx_enable_ms(&s->port);
// request irq
if(request_irq(s->port.irq, wk2xxx_irq,IRQF_SHARED|IRQF_TRIGGER_LOW,"wk2xxxspi", s) < 0)
{
dev_warn(&s->spi_wk->dev, "cannot allocate irq %d\n", s->irq);
s->port.irq = 0;
#ifdef _DEBUG_tla001
printk(KERN_ALERT "****** start_tx_fail=1*****\n");
#endif
destroy_workqueue(s->workqueue);
s->workqueue = NULL;
return -EBUSY;
} udelay(100);
udelay(100);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_startup------exit---\n");
#endif
return 0;
}
//* Power down all displays on reboot, poweroff or halt *
static void wk2xxx_shutdown(struct uart_port *port)//
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_shutdown------in---\n");
#endif
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
if (s->suspending)
return;
s->force_end_work = 1;
if (s->workqueue)
{
flush_workqueue(s->workqueue);
destroy_workqueue(s->workqueue);
s->workqueue = NULL;
}
if (s->port.irq)
{
disable_irq_nosync(s->port.irq);
printk(KERN_ALERT "irq---%d\n",s->port.line);
free_irq(s->port.irq,s);
}
//printk("work_pending() =: %d tx_empty_flag = : %d start_tx_flag = :%d stop_tx_flag = :%d conf_flag =: %d irq_flag =: %d tx_empty=:%d\n",work_pending(&s->work),s->tx_empty_flag,s->start_tx_flag,s->stop_tx_flag,s->stop_rx_flag,s->conf_flag,s-> irq_flag,s->tx_empty);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_shutdown-----exit---\n");
#endif
return;
}
static void conf_wk2xxx_subport(struct uart_port *port)//i
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-conf_wk2xxx_subport------in---\n");
#endif
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
uint8_t old_sier,lcr,scr,scr_ss,dat[1],gena,test1,baud0_ss,baud1_ss,pres_ss;
lcr = s->new_lcr;
scr_ss = s->new_scr;
baud0_ss=s->new_baud0;
baud1_ss=s->new_baud1;
pres_ss=s->new_pres;
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER ,dat);
old_sier = dat[0];
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER ,old_sier&(~(WK2XXX_TFTRIG_IEN | WK2XXX_RFTRIG_IEN | WK2XXX_RXOUT_IEN)));
//local_irq_restore(flags);
do{
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_FSR,dat);
//ssr = dat[0];
} while (dat[0] & WK2XXX_TBUSY);
// then, disable everything
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR,dat);
scr = dat[0];
scr &= 0x0f;
scr |= scr_ss;
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR ,scr&(~(WK2XXX_RXEN|WK2XXX_TXEN)));
// set the parity, stop bits and data size //
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_LCR ,lcr);
// set the baud rate //
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SIER ,old_sier);
// wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR ,scr|(WK2XXX_RXEN|WK2XXX_TXEN));
// set the baud rate //
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,1);
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD0 ,baud0_ss);
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD1 ,baud1_ss);
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_PRES ,pres_ss);
#ifdef _DEBUG_WK2XXX2
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD0,dat);
printk(KERN_ALERT ":WK2XXX_BAUD0=0x%X\n", dat[0]);
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_BAUD1,dat);
printk(KERN_ALERT ":WK2XXX_BAUD1=0x%X\n", dat[0]);
wk2xxx_read_reg(s->spi_wk,s->port.iobase,WK2XXX_PRES,dat);
printk(KERN_ALERT ":WK2XXX_PRES=0x%X\n", dat[0]);
#endif
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SPAGE ,0);
wk2xxx_write_reg(s->spi_wk,s->port.iobase,WK2XXX_SCR ,scr|(WK2XXX_RXEN|WK2XXX_TXEN) );
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-conf_wk2xxx_subport------exit---\n");
#endif
}
// change speed
static void wk2xxx_termios( struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-vk32xx_termios------in---\n");
#endif
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
int baud = 0;
uint8_t lcr,scr,baud1,baud0,pres;
unsigned short cflag;
unsigned short lflag;
//u32 param_new, param_mask;
// mutex_lock(&wk2xxxs_lock);
cflag = termios->c_cflag;
lflag = termios->c_lflag;
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "cflag := 0x%X lflag : = 0x%X\n",cflag,lflag);
#endif
baud1=0;
baud0=0;
pres=0;
baud = tty_termios_baud_rate(termios);
switch (baud) {
case 600:
baud1=0x4;
baud0=0x7f;
pres=0;
break;
case 1200:
baud1=0x2;
baud0=0x3F;
pres=0;
break;
case 2400:
baud1=0x1;
baud0=0x1f;
pres=0;
break;
case 4800:
baud1=0x00;
baud0=0x8f;
pres=0;
break;
case 9600:
baud1=0x00;
baud0=0x47;
pres=0;
break;
case 19200:
baud1=0x00;
baud0=0x23;
pres=0;
break;
case 38400:
baud1=0x00;
baud0=0x11;
pres=0;
break;
case 76800:
baud1=0x00;
baud0=0x08;
pres=0;
break;
case 1800:
baud1=0x01;
baud0=0x7f;
pres=0;
break;
case 3600:
baud1=0x00;
baud0=0xbf;
pres=0;
break;
case 7200:
baud1=0x00;
baud0=0x5f;
pres=0;
break;
case 14400:
baud1=0x00;
baud0=0x2f;
pres=0;
break;
case 28800:
baud1=0x00;
baud0=0x17;
pres=0;
break;
case 57600:
baud1=0x00;
baud0=0x0b;
pres=0;
break;
case 115200:
baud1=0x00;
baud0=0x05;
pres=0;
#ifdef _DEBUG_tla001
printk(KERN_ALERT "set baud=115200bps\n");
#endif
break;
case 230400:
baud1=0x00;
baud0=0x02;
pres=0;
break;
default:
baud1=0x00;
baud0=0x00;
pres=0;
}
tty_termios_encode_baud_rate(termios, baud, baud);
/* we are sending char from a workqueue so enable */
//spin_lock(&s->conf_lock);
//s->port.state->port.tty->low_latency = 1;
//termios->c_lflag &= ~ECHO;
lcr =0;
if (cflag & CSTOPB)
lcr|=WK2XXX_STPL;//two stop_bits
else
lcr&=~WK2XXX_STPL;//one stop_bits
if (cflag & PARENB) {
lcr|=WK2XXX_PAEN;//enbale spa
if (!(cflag & PARODD)){
lcr |= WK2XXX_PAM0;//PAM0=1
lcr &= ~WK2XXX_PAM0;//PAM1=0
}
else{
lcr |= WK2XXX_PAM1;
lcr &= ~WK2XXX_PAM0;
}
}
else{
lcr&=~WK2XXX_PAEN;
}
//scr = 0;
//scr &= 0x0f;
//scr |= param_new<<4;
s->new_baud1=baud1;
s->new_baud0=baud0;
s->new_pres=pres;
//spin_lock(&s->conf_lock);
//s->conf_flag =1;
s->new_lcr = lcr;
s->new_scr = scr;
//spin_unlock(&s->conf_lock);
//vk32xx_dowork(s);
if(!(s->conf_flag|| s->conf_fail))
{
if(wk2xxx_dowork(s))
{
s->conf_flag =1;
}
else
{
s->conf_fail =1;
}
}
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-vk32xx_termios------exit---\n");
#endif
// mutex_unlock(&wk2xxxs_lock);
return ;
}
static const char *wk2xxx_type(struct uart_port *port)
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "wk2xxx_type-------------out-------- \n");
#endif
return port->type == PORT_WK2XXX ? "wk2xxx" : NULL;//this is defined in serial_core.h
}
/*
* Release the memory region(s) being used by 'port'.
*/
static void wk2xxx_release_port(struct uart_port *port)
{
printk(KERN_ALERT "wk2xxx_release_port\n");
// struct vk32xx_port *s = container_of(port,struct vk32xx_port,port);
// dev_dbg(&s->spi_vk->dev, "%s\n", __func__);
//no such memory region for vk32
}
/*
* Request the memory region(s) being used by 'port'.
*/
static int wk2xxx_request_port(struct uart_port *port)//no such memory region needed for vk32
{
printk(KERN_ALERT "wk2xxx_request_port\n");
// struct vk32xx_port *s = container_of(port,struct vk32xx_port,port);
return 0;
}
/*
* Configure/autoconfigure the port*/
static void wk2xxx_config_port(struct uart_port *port, int flags)
{
struct wk2xxx_port *s = container_of(port,struct wk2xxx_port,port);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "wk2xxx_config_port \n");
#endif
if (flags & UART_CONFIG_TYPE && wk2xxx_request_port(port) == 0)
s->port.type = PORT_WK2XXX;
}
/*
* Verify the new serial_struct (for TIOCSSERIAL).
* The only change we allow are to the flags and type, and
* even then only between PORT_vk32xx and PORT_UNKNOWN
*/
static int wk2xxx_verify_port(struct uart_port *port, struct serial_struct *ser)
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "wk2xxx_verify_port \n");
#endif
int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_WK2XXX)
ret = -EINVAL;
if (port->irq != ser->irq)
ret = -EINVAL;
if (ser->io_type != SERIAL_IO_PORT)
ret = -EINVAL;
//if (port->uartclk / 16 != ser->baud_base)//?a??2?猫路?篓
// ret = -EINVAL;
if (port->iobase != ser->port)
ret = -EINVAL;
if (ser->hub6 != 0)
ret = -EINVAL;
return ret;
}
static struct uart_ops wk2xxx_pops = {
tx_empty: wk2xxx_tx_empty,
set_mctrl: wk2xxx_set_mctrl,
get_mctrl: wk2xxx_get_mctrl,
stop_tx: wk2xxx_stop_tx,
start_tx: wk2xxx_start_tx,
stop_rx: wk2xxx_stop_rx,
enable_ms: wk2xxx_enable_ms,
break_ctl: wk2xxx_break_ctl,
startup: wk2xxx_startup,
shutdown: wk2xxx_shutdown,
set_termios: wk2xxx_termios,
type: wk2xxx_type,
release_port: wk2xxx_release_port,
request_port: wk2xxx_request_port,
config_port: wk2xxx_config_port,
verify_port: wk2xxx_verify_port,
};
static struct uart_driver wk2xxx_uart_driver = {
owner: THIS_MODULE,
major: SERIAL_WK2XXX_MAJOR,
#ifdef CONFIG_DEVFS_FS
driver_name: "ttySWK",
dev_name: "ttysWK",
#else
driver_name: "ttySWK",
dev_name: "ttysWK",
#endif
minor: MINOR_START,
nr: NR_PORTS,
cons: NULL//WK2Xxx_CONSOLE,
};
static int uart_driver_registered;
int wk2166_irq1;
static int __devinit wk2xxx_probe(struct spi_device *spi)
{
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_probe()------in---\n");
#endif
uint8_t i;
int status;
i=0;
/* static volatile unsigned long *gpbcon_addr;
#define GPBCONWWWWW 0xE020004C
gpbcon_addr = ioremap(GPBCONWWWWW, 4);
status = *gpbcon_addr;
printk(KERN_ERR "GPB_DRV...........= 0x%X\n",status);
*gpbcon_addr |= 0xaa00;
status = *gpbcon_addr;
printk(KERN_ERR "GPB_DRV...........= 0x%X\n",status);
printk(KERN_ALERT "wk2xxx_probe wk2xxx\n");*/
mutex_lock(&wk2xxxs_lock);
if(!uart_driver_registered)
{
uart_driver_registered = 1;
status=uart_register_driver(&wk2xxx_uart_driver);
if (status)
{
printk(KERN_ALERT "Couldn't register wk2xxx uart driver\n");
mutex_unlock(&wk2xxxs_lock);
return status;
}
}
printk(KERN_ALERT "wk2xxx_serial_init()\n");
/********IO初始化***********/
gpio_free(wk2166_irq);
gpio_request(wk2166_irq,"wk2166_irq");
gpio_direction_input(wk2166_irq);
wk2166_irq1=gpio_to_irq(wk2166_irq);
printk(KERN_ALERT "wk2166_irq1=%d\n",wk2166_irq1);
for(i =0;i<NR_PORTS;i++)
{
struct wk2xxx_port *s = &wk2xxxs[i];//container_of(port,struct vk32xx_port,port);
s->tx_done =0;
s->spi_wk = spi;
s->port.line = i;
s->port.ops = &wk2xxx_pops;
s->port.uartclk = WK_CRASTAL_CLK;
s->port.fifosize = 256;
s->port.iobase = i+1;
s->port.irq = wk2166_irq1;
s->port.iotype = SERIAL_IO_PORT;
s->port.flags = ASYNC_BOOT_AUTOCONF;
//s->minor = i;
status = uart_add_one_port(&wk2xxx_uart_driver, &s->port);
if(status<0)
{
//dev_warn(&spi->dev,"uart_add_one_port failed for line i:= %d with error %d\n",i,status);
printk(KERN_ALERT "uart_add_one_port failed for line i:= %d with error %d\n",i,status);
}
}
printk(KERN_ALERT "uart_add_one_port = 0x%d\n",status);
mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
// while(1)
// wk2xxx_read_reg(s->spi_wk,WK2XXX_GPORT,WK2XXX_GENA,0XFF);
printk(KERN_ALERT "-wk2xxx_probe()------exit---\n");
#endif
return 0;
}
/*
static int vk32xx_suspend(struct spi_device *spi)
{
printk(KERN_ALERT "vk32xx_suspend vk32xx");
return 0;
}
*/
static int __devexit wk2xxx_remove(struct spi_device *spi)
{
//struct wk2xxx_port *s = dev_get_drvdata(&spi->dev);
int i;
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_remove()------in---\n");
#endif
mutex_lock(&wk2xxxs_lock);
for(i =0;i<NR_PORTS;i++)
{
struct wk2xxx_port *s = &wk2xxxs[i];
uart_remove_one_port(&wk2xxx_uart_driver, &s->port);
}
printk(KERN_ALERT "removing wk2xxx driver\n");
uart_unregister_driver(&wk2xxx_uart_driver);
mutex_unlock(&wk2xxxs_lock);
#ifdef _DEBUG_WK2XXX
printk(KERN_ALERT "-wk2xxx_remove()------exit---\n");
#endif
/***********释放中断号*************************/
free_irq(wk2166_irq1,1);
gpio_free(wk2166_irq);
return 0;
}
static int wk2xxx_resume(struct spi_device *spi)
{
printk(KERN_ALERT "resume wk2xxx");
return 0;
}
static struct spi_driver wk2xxx_driver = {
.driver = {
.name = "wk2166",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = wk2xxx_probe,
.remove = __devexit_p(wk2xxx_remove),
.resume = wk2xxx_resume,
};
static int __init wk2xxx_init(void)
{
int retval;
mxc_iomux_v3_setup_pad(MX6Q_PAD_SD3_DAT2__GPIO_7_6);
//mxc_iomux_v3_setup_pad(MX6Q_PAD_SD3_CMD__GPIO_7_2);
mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_CS0__ECSPI2_SCLK);
mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_CS1__ECSPI2_MOSI);
mxc_iomux_v3_setup_pad(MX6Q_PAD_EIM_OE__ECSPI2_MISO);
mxc_iomux_v3_setup_pad(MX6Q_PAD_CSI0_DAT11__GPIO_5_29);
__gpio_set_value(wk2166__cs,1);
retval = spi_register_driver(&wk2xxx_driver);
printk(KERN_ALERT "rgister spi return v = :%d\n",retval);
return retval;
}
static void __exit wk2xxx_exit(void)
{
spi_unregister_driver(&wk2xxx_driver);
printk(KERN_ALERT "TEST_REG:quit ");
}
module_init(wk2xxx_init);
module_exit(wk2xxx_exit);
MODULE_AUTHOR("WKIC Ltd");
MODULE_DESCRIPTION("wk2xxx generic serial port driver");
MODULE_LICENSE("GPL");
wkXXX.h
#ifndef _SERIAL_WK2166_H #define _SERIAL_WK2166_H //#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/console.h> //#include <linux/serial_core.h> #include <asm/irq.h> #include <asm/io.h> //#include <asm/hardware.h> //EINT15 GPG7 //wkxxxx Global rigister address defines #define WK2XXX_GENA 0X00 //全局控制寄存器 #define WK2XXX_GRST 0X01 //全局子串口复位寄存器 #define WK2XXX_GMUT 0X02 #define WK2XXX_GIER 0X10 //全局中断寄存器 #define WK2XXX_GIFR 0X11 //全局中断标志寄存器 #define WK2XXX_GPDIR 0X21 #define WK2XXX_GPDAT 0X31 #define WK2XXX_GPORT 1 // //wkxxxx slave uarts rigister address defines #define WK2XXX_SPAGE 0X03 //子串口页控制寄存器 //PAGE0 #define WK2XXX_SCR 0X04 //子串口使能寄存器 #define WK2XXX_LCR 0X05 //子串口配置寄存器 #define WK2XXX_FCR 0X06 //子串口FIFO控制寄存器 #define WK2XXX_SIER 0X07 //子串口中断使能寄存器 #define WK2XXX_SIFR 0X08 //子串口中断标志寄存器 #define WK2XXX_TFCNT 0X09 //子串口发送FIFO计数寄存器 #define WK2XXX_RFCNT 0X0A //子串口接收FIFO计数寄存器 #define WK2XXX_FSR 0X0B //子串口FIFO状态寄存器 #define WK2XXX_LSR 0X0C //子串口接收状态寄存器 #define WK2XXX_FDAT 0X0D //子串口FIFO数据寄存器 #define WK2XXX_FWCR 0X0E // #define WK2XXX_RS485 0X0F // //PAGE1 #define WK2XXX_BAUD1 0X04 //子串口波特率配置寄存器高字节 #define WK2XXX_BAUD0 0X05 //子串口波特率配置寄存器低字节 #define WK2XXX_PRES 0X06 //子串口波特率配置寄存器小数部分 #define WK2XXX_RFTL 0X07 //子串口接收FIFO中断触发点配置寄存器 #define WK2XXX_TFTL 0X08 //子串口发送FIFO中断触发点配置寄存器 #define WK2XXX_FWTH 0X09 // #define WK2XXX_FWTL 0X0A // #define WK2XXX_XON1 0X0B // #define WK2XXX_XOFF1 0X0C // #define WK2XXX_SADR 0X0D // #define WK2XXX_SAEN 0X0D // #define WK2XXX_RRSDLY 0X0F // /******全局控制寄存器GENA******/ #define WK2XXX_UT4EN 0x08 //子串口4时钟使能位 #define WK2XXX_UT3EN 0x04 //子串口3时钟使能位 #define WK2XXX_UT2EN 0x02 //子串口2时钟使能位 #define WK2XXX_UT1EN 0x01 //子串口1时钟使能位 /***全局子串口复位寄存器GRST***/ #define WK2XXX_UT4SLEEP 0x80 //子串口4休眠状态位 #define WK2XXX_UT3SLEEP 0x40 //子串口3休眠状态位 #define WK2XXX_UT2SLEEP 0x20 //子串口2休眠状态位 #define WK2XXX_UT1SLEEP 0x10 //子串口1休眠状态位 #define WK2XXX_UT4RST 0x08 //子串口4软复位控制位 #define WK2XXX_UT3RST 0x04 //子串口3软复位控制位 #define WK2XXX_UT2RST 0x02 //子串口2软复位控制位 #define WK2XXX_UT1RST 0x01 //子串口1软复位控制位 /******全局中断寄存器GIER******/ #define WK2XXX_UT4IE 0x08 //子串口4中断使能控制位 #define WK2XXX_UT3IE 0x04 //子串口3中断使能控制位 #define WK2XXX_UT2IE 0x02 //子串口2中断使能控制位 #define WK2XXX_UT1IE 0x01 //子串口1中断使能控制位 /****全局中断标志寄存器GIFR****/ #define WK2XXX_UT4INT 0x08 //子串口4中断标志位 #define WK2XXX_UT3INT 0x04 //子串口3中断标志位 #define WK2XXX_UT2INT 0x02 //子串口2中断标志位 #define WK2XXX_UT1INT 0x01 //子串口1中断标志位 /****子串口页控制寄存器SPAGE***/ #define WK2XXX_SPAGE0 0x00 //PAGE0 #define WK2XXX_SPAGE1 0x01 //PAGE1 /*****子串口控制寄存器SCR******/ #define WK2XXX_SLEEPEN 0x04 //子串口休眠使能位 #define WK2XXX_TXEN 0x02 //子串口发送使能位 #define WK2XXX_RXEN 0x01 //子串口接收使能位 /*****子串口配置寄存器LCR******/ #define WK2XXX_BREAK 0x20 //子串口Line-Break输出控制位 #define WK2XXX_IREN 0x10 //子串口红外使能位 #define WK2XXX_PAEN 0x08 //子串口校验使能位 #define WK2XXX_PAM1 0x04 //子串口校验模式选择位00:0 校验;01:奇校验; #define WK2XXX_PAM0 0x02 //子串口校验模式选择位10:偶校验;11:1 校验 #define WK2XXX_STPL 0x01 //子串口停止位长度控制位0:1bit;1:2bit /****子串口FIFO控制寄存FRC*****/ /****子串口FIFO控制寄存SIER****/ #define WK2XXX_FERR_IEN 0x80 //接收FIFO数据错误中断使能位 #define WK2XXX_CTS_IEN 0x40 // #define WK2XXX_RTS_IEN 0x20 // #define WK2XXX_XOFF_IEN 0x10 // #define WK2XXX_TFEMPTY_IEN 0x08 //发送FIFO空中断使能位 #define WK2XXX_TFTRIG_IEN 0x04 //发送FIFO触点中断使能位 #define WK2XXX_RXOUT_IEN 0x02 //接收FIFO超时中断使能位 #define WK2XXX_RFTRIG_IEN 0x01 //接收FIFO触点中断使能位 /****子串口FIFO控制寄存SIFR****/ #define WK2XXX_FERR_INT 0x80 //接收FIFO数据错误中断标志位 #define WK2XXX_CTS_INT 0x40 // #define WK2XXX_RTS_INT 0x20 // #define WK2XXX_XOFF_INT 0x10 // #define WK2XXX_TFEMPTY_INT 0x08 //发送FIFO空中断标志位 #define WK2XXX_TFTRIG_INT 0x04 //发送FIFO触点中断标志位 #define WK2XXX_RXOVT_INT 0x02 //接收FIFO超时中断标志位 #define WK2XXX_RFTRIG_INT 0x01 //接收FIFO触点中断标志位 /*子串口发送FIFO计数寄存器TFCNT*/ /**子串口接收FIFO计数寄存RFCNT**/ /****子串口FIFO 状态寄存FSR****/ #define WK2XXX_RFOE 0x80 //子串口接收FIFO中数据溢出出错标志位 #define WK2XXX_RFBI 0x40 //子串口接收FIFO中数据有Line-Break错误 #define WK2XXX_RFFE 0x20 //子串口接收FIFO中数据帧错误标志位 #define WK2XXX_RFPE 0x10 //子串口接收FIFO中数据校验错误标志位 #define WK2XXX_RDAT 0x08 //子串口接收FIFO空标志位 #define WK2XXX_TDAT 0x04 //子串口发送FIFO空标志位 #define WK2XXX_TFULL 0x02 //子串口发送FIFO满标志位 #define WK2XXX_TBUSY 0x01 //子串口发送TX忙标志位 /***子串口接收状态寄存器LSR****/ #define WK2XXX_OE 0x08 //子串口接收FIFO当前被读取的字节溢出出错标志位 #define WK2XXX_BI 0x04 //子串口接收FIFO中当前被读取字节Line-Break错误标志位 #define WK2XXX_FE 0x02 //子串口接收FIFO中当前被读取字节帧错误标志位 #define WK2XXX_PE 0x01 //子串口接收FIFO中当前被读取字节校验错误标志位 //FWCR //RS485 // #define NR_PORTS 4 // #define SERIAL_WK2XXX_MAJOR 207 #define CALLOUT_WK2XXX_MAJOR 208 #define MINOR_START 5 //wk2xxx hardware configuration #define IRQ_WK2XXX_PIN IMX_GPIO_NR(5, 17) #define IRQ_WK2XXX __gpio_to_irq(IRQ_WK2XXX_PIN)//shuould be IRQ_EINT7,but EINT7 of the borad is ocuppied #define WK_CS_PIN IMX_GPIO_NR(2, 26)//should be GPB #define WK_CRASTAL_CLK (3686400*2) #define WK2XXX_CS WK_CS_PIN #define MAX_WK2XXX 4 #define WK2XXX_ISR_PASS_LIMIT 50 //#define _DEBUG_WK2XXX #define PORT_WK2XXX 1 #endif
如果cs信号不能拉低,需要手动拉低,并在spi传输的时候,加锁,不然4路同时读写的时候会冲突
此外,针对不同的外置晶振,需要重新配置波特率的控制字
IMX6下移植WKxxx驱动的更多相关文章
- 第一章 Android系统移植与驱动开发概述
本书第一章首先简单概要地介绍了关于Android系统移植和驱动开发的相关内容. 所谓“移植”是指为特定的自己的设备,如手机定制Android的过程.自己开发一些程序(移植)装载在设备上,使得Andro ...
- 第一章Android系统移植与驱动开发概述--读书笔记
以前,初步学习过嵌入式Linux驱动开发的基础课程,对于驱动开发可以说是有了一点点微末的基础吧.首先我们要对Android嵌入式系统有一个初步的认识,Android系统发展到今天已经具备了完善的架构. ...
- 1Android系统移植与驱动开发概述
1.Android系统架构分为四层,从下至上依次为Linux内核层,C/C++代码库.Android SDK API.应用程序,要熟悉每一层的内容以及功能: 2.Android移植分为应用移植和系统移 ...
- Android系统移植与驱动开发----第一章
第一章 Android系统移植与驱动开发 Android源代码定制完全属于自己的嵌入式系统,但是支持的设备不多,所以要移植,而在移植的过程中使用的不得不提的是驱动开发. Android系统构架主要包括 ...
- 【转】 linux内核移植和驱动添加(三)
原文网址:http://blog.chinaunix.net/uid-29589379-id-4708909.html 原文地址:linux内核移植和驱动添加(三) 作者:genehang 四,LED ...
- 3.移植驱动到3.4内核-移植DM9000C驱动
在上章-使内核支持烧写yaffs2,裁剪内核并制作补丁了 本章,便开始移植以前2.6内核的驱动到3.4新内核 1.介绍 首先内核更新,有可能会重新定义新的宏,去除以前的宏,以前更改函数名等 所以移植驱 ...
- backports移植rtlwifi驱动
/************************************************************************ * backports移植rtlwifi驱动 * 说 ...
- 基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- I.mx6s上移植wm8960驱动(基于linux3.0.101版本)
I.mx6s上移植wm8960驱动 此篇博文只记录移植的步骤,其他不做分析.首先上一张wm8960的硬件连接图: 1 上电操作 配置wm8960的上电脚,文件位置:arch/arm/mach ...
随机推荐
- UI的一些方法(按钮和线)
//设置按钮字体颜色 [self.determineBtn setTitleColor:[UIColor colorWithHexString:@"0xff9500"] forSt ...
- JVM-程序编译与代码早期(编译期)优化
早期(编译期)优化 一.Javac编译器 1.Javac的源代码与调试 Javac的源代码放在JDK_SRC_HOME/langtools/src/shares/classes/com/sun/too ...
- 循环打印i值(面试题)
/* * 下面的代码,为了实现每隔1秒说一句话, * 找出存在的问题,并改正,然后描述一下你的解决方案. * */ var arr = [ '第一句话', '第二句话', '第三句话', '第四句话' ...
- yum命令详解
yum(全 称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器.基於RPM包管理,能够从指定的服务器自动下载 ...
- matlab使用
1.nargin 在matlab中定义一个函数时, 在函数体内部, nargin是用来判断输入变量个数的函数. 2.assert “断言”,“坚持自己的主张”.判断函数. http://www.cnb ...
- B/S和C/S测试的区别
B/S(Brower/Server)以访问方式为主,包含客户端浏览器.web应用服务器.数据库服务器的软件系统.一般的B/S结构,都是多层架构的,有界面层.业务逻辑层.数据层.由于这种结构不需 ...
- 地址(Address)——WCF学习笔记(2)
地址(Address)分为: 统一资源表示(URI). EndpointAddress. 端口共享. 逻辑地址与物理地址. 请求监听与消息分发.
- web安全之http协议
http协议 全称是超文本传输协议,是web的核心传输机制,也是服务端和客户端之间交换url的首选协议. url url全称是统一资源定器(统一资源标识符) 顾名思义 每一条格式正确且规范,但url都 ...
- XPath注入笔记
XPath注入 XQuery注入 测试语句:'or '1'='1 利用工具: Xcat介绍 Xcat是python的命令行程序利用Xpath的注入漏洞在Web应用中检索XML文档 下载地址:https ...
- IEnumerable 和 IQueryable 区别
IQueryable继承自IEnumerable,所以对于数据遍历来说,它们没有区别. 但是IQueryable的优势是它有表达式树,所有对于IQueryable的过滤,排序等操作,都会先缓存到表达式 ...