⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial_vk32xx.c

📁 vk3x系列串口扩展芯片在linux下的SPI接口驱动源码和测试应用程序源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*	VKIC Co. Ltd. 2007
*	By  Huangwei 
*
*/

#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/hardware.h>
#include "serial_vk32xx.h"

static void vk32xx_tx_chars(struct uart_info *info);
inline  void setup_spi(void)
{
	SPCON0=SPCON_MSTR|SPCON_ENSCK;
	//config SPPIN
	//USE DEFAULT VALLUE
	//config the baud rate register SPPRE
	SPPRE0=0x04;//set bandrate
		    //0x0f->2.1M Hz
		    //0x08->3.7M Hz
		    //0x04->6.67M Hz
	write_gpio_bit(VK32_CS,1);		
}

uint8_t spi_send_byte(uint8_t dat)
{
	write_gpio_bit(VK32_CS,0);
 	SPTDAT0=dat;
	while(!(SPSTA0&SPSTA_READY));
	write_gpio_bit(VK32_CS,1);
	return SPRDAT0;
}

void vk3xxx_write_reg(uint8_t port,uint8_t reg,uint8_t dat)
{
	spi_send_byte(0x80|((port-1)<<5)|(reg<<1));
	spi_send_byte(dat);
}

uint8_t vk3xxx_read_reg(uint8_t port,uint8_t reg)
{
	spi_send_byte(((port-1)<<5)+(reg<<1));
	return spi_send_byte(0x00);
}

static struct tty_driver normal, callout;
static struct tty_struct *vk32xx_table[NR_PORTS];
static struct termios *vk32xx_termios[NR_PORTS], *vk32xx_termios_locked[NR_PORTS];
//static int (*vk32xx_open)(struct uart_port *, struct uart_info *);
static void (*vk32xx_close)(struct uart_port *, struct uart_info *);

/*
 * interrupts disabled on entry
 */
static void vk32xx_stop_tx(struct uart_port *port, u_int from_tty)
{
	
		//disable the interrupt,clear the corresponding bit in GIR 
		uint8_t	sier;
		sier=vk3xxx_read_reg(port->iobase,VK32XX_SIER);
		sier&=~VK32XX_TRIEN;
		vk3xxx_write_reg(port->iobase,VK32XX_SIER,sier);
#ifdef _DEBUG_VK32XX
		printk(KERN_ALERT "vk32xx_stop_tx\n");
#endif
}

/*
 * interrupts may not be disabled on entry
 */
static void vk32xx_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
{
	struct uart_info * info =(struct uart_info *)(port->membase);
//	printk(KERN_ALERT "vk32xx_start_tx\n");
	if (nonempty) {					
		//unsigned long flags;
		uint8_t sier;

#ifdef _DEBUG_VK32XX
		uint8_t gir,sier,sifr;
		printk(KERN_ALERT "VK32XX_start_tx nonempty\n");
#endif
		
		sier=vk3xxx_read_reg(port->iobase,VK32XX_SIER);
		sier|=VK32XX_TRIEN;
		vk3xxx_write_reg(port->iobase,VK32XX_SIER,sier);
		
#ifdef _DEBUG_VK32XX
		sier=vk3xxx_read_reg(port->iobase,VK32XX_SIER);
	//	sifr|=TFINT;
	//	vk3xxx_write_reg(port->iobase,SIFR,sifr);
	//	sifr=vk3xxx_read_reg(port->iobase,SIFR);
	//	printk(KERN_ALERT "sifr:%x\n",sifr);
		
		gir=vk3xxx_read_reg(port->iobase,VK32XX_GIR);
		sifr=vk3xxx_read_reg(port->iobase,VK32XX_SIFR);
		printk(KERN_ALERT "gir:%x sifr:%x sier:%x\n",gir,sifr,sier);	
		//local_irq_restore(flags);
#endif
		
//		vk32xx_tx_chars(info);
		enable_irq(port->irq);
	}
}

/*
 * Interrupts enabled
 */
static void vk32xx_stop_rx(struct uart_port *port)
{
									//disable the rx interrupt
		uint8_t	sier;
#ifdef _DEBUG_VK32XX
		printk(KERN_ALERT "stop_rx\n");
#endif
		sier=vk3xxx_read_reg(port->iobase,VK32XX_SIER);
		sier&=~VK32XX_RFIEN;
		vk3xxx_write_reg(port->iobase,VK32XX_SIER,sier);
}

/*
 * No modem control lines
 */
static void vk32xx_enable_ms(struct uart_port *port)	//nothing
{
}

static void
vk32xx_rx_chars(struct uart_info *info, struct pt_regs *regs)
{
	uint8_t ssr;
	struct tty_struct *tty = info->tty;
	unsigned int ch, flg, ignored = 0;
	struct uart_port *port = info->port;

	//得到状态
	//此处需要得到SSR值
#ifdef _DEBUG_VK32XX1
	printk(KERN_ALERT "vk32xx_rx_chars()\n");
#endif
	ssr=vk3xxx_read_reg(port->iobase,VK32XX_SSR);
	
	
	while (!(ssr& VK32XX_RFEM)){//接收FIFO不空
		ch =vk3xxx_read_reg(port->iobase,VK32XX_SFDR); ;//得到一个字符的数据

		if (tty->flip.count >= TTY_FLIPBUF_SIZE){
			printk(KERN_ALERT "1\n");
			goto ignore_char;
		}
		port->icount.rx++;
#ifdef _DEBUG_VK32XX1
		printk(KERN_ALERT __FUNCTION__ "icount.rx:%d\n",port->icount.rx);
#endif
		flg = TTY_NORMAL;

		/*
		 * note that the error handling code is
		 * out of the main execution path
		 */
		if (ssr&(VK32XX_OE|VK32XX_FE|VK32XX_PE)){//是否有错
			printk(KERN_ALERT "2\n");
			goto handle_error;
			
		}
		if (uart_handle_sysrq_char(info, ch, regs))
			goto ignore_char;

	error_return:
		*tty->flip.flag_buf_ptr++ = flg;
		*tty->flip.char_buf_ptr++ = ch;
		tty->flip.count++;
#ifdef _DEBUG_VK32XX1
		printk(KERN_ALERT __FUNCTION__ " flip.count:%d char:%d\n",tty->flip.count,ch);
#endif
	ignore_char:
							
		ssr=vk3xxx_read_reg(port->iobase,VK32XX_SSR);//得到更新的状态
	}
out:
	tty_flip_buffer_push(tty);
	return;

handle_error:
	if (ssr & VK32XX_PE)//检查是哪种错误, 并对其进行计数
		port->icount.parity++;
	if (ssr & VK32XX_FE)
		port->icount.frame++;
	if (ssr & VK32XX_OE)
		port->icount.overrun++;

	//if (ssr & port->ignore_status_mask) {//忽略它并计数
																					//!!!!此处mask没有实现, 则只要有错全部忽略
		if (++ignored > 100)
			goto out;
		goto ignore_char;

#ifdef SUPPORT_SYSRQ
	info->sysrq = 0;
#endif
	goto error_return;
}

static void vk32xx_tx_chars(struct uart_info *info)
{
	struct uart_port * port = info->port;
	uint8_t ssr;
	printk(KERN_ALERT "tx_chars\n");
	if (port->x_char) {
		
		//向FIFO写入一个数据
		vk3xxx_write_reg(port->iobase,VK32XX_SFDR,port->x_char);
		port->icount.tx++;
		port->x_char = 0;
		return;
	}
	if (info->xmit.head == info->xmit.tail
	    || info->tty->stopped
	    || info->tty->hw_stopped) {
		vk32xx_stop_tx(info->port, 0);
		return;
	}
	/*
	 * Tried using FIFO (not checking TNF) for fifo fill:
	 * still had the '4 bytes repeated' problem.
	 */
	 ssr=vk3xxx_read_reg(port->iobase,VK32XX_SSR);
#ifdef _DEBUG_VK32XX
	printk(KERN_ALERT "ssr:%x\n",ssr);
#endif
	while (!(ssr & VK32XX_TFFL)){//发送FIFO为空则继续发
		//printk(KERN_ALERT "sending\n");
	//	printk(KERN_ALERT "tx char:%d\n",info->xmit.buf[info->xmit.tail]);
		vk3xxx_write_reg(port->iobase,VK32XX_SFDR,info->xmit.buf[info->xmit.tail]);
		info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
#ifdef _DEBUG_VK32XX1
		printk(KERN_ALERT "xmit.head:%d,xmit.tail:%d,char:%d\n",info->xmit.head,info->xmit.tail,info->xmit.buf[info->xmit.tail]);
#endif
		if (info->xmit.head == info->xmit.tail)
			break;
	 	ssr=vk3xxx_read_reg(port->iobase,VK32XX_SSR);
	}
	printk(KERN_ALERT "ssr:%x\n",ssr);
	if (CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) <
			WAKEUP_CHARS)
		uart_event(info, EVT_WRITE_WAKEUP);

	if (info->xmit.head == info->xmit.tail)
		vk32xx_stop_tx(info->port, 0);
}

static void vk32xx_int(int irq, void *dev_id, struct pt_regs *regs)
{
	struct uart_info *info = dev_id;
	struct uart_port *port = info->port;
	unsigned int pass_counter = 0;
	uint8_t sifr,gir,sier;
	gir=vk3xxx_read_reg(port->iobase,VK32XX_GIR);
#ifdef _DEBUG_VK32XX
	printk(KERN_ALERT "vk32xx_int()gir:%x\n",gir);
#endif
	switch(port->iobase){
		case 1 :
						if(!(gir & VK32XX_U1IF))//这个子通道没有中断
								return;
						break;	
		case 2 :
						if(!(gir & VK32XX_U2IF))//这个子通道没有中断
								return;	
						break;
		case 3 :
						if(!(gir & VK32XX_U3IF))//这个子通道没有中断
								return;	
						break;
		case 4 :
						if(!(gir & VK32XX_U4IF))//这个子通道没有中断
								return;																			
						break;
		default:
						break;
	}
	
	sifr=vk3xxx_read_reg(port->iobase,VK32XX_SIFR);//读取状态判断是哪里产生的中断。对vk32读取SIFR
	sier=vk3xxx_read_reg(port->iobase,VK32XX_SIER);//读取状态判断是哪里产生的中断。对vk32读取SIFR
	//这里mask没有实现,则不需要屏蔽
	
#ifdef _DEBUG_VK32XX
	printk(KERN_ALERT "vk32xx_int()sifr:%x sier:%x \n",sifr,sier);
#endif
	do {
		if (sifr&VK32XX_RFINT) {//是否发送中断
			printk(KERN_ALERT "			in inttrupt rx_chars\n");
			vk32xx_rx_chars(info, regs);
		}

		if ((sifr & VK32XX_TFINT)&&(sier & VK32XX_TRIEN)){
			printk(KERN_ALERT "			int tx_char\n");
			vk32xx_tx_chars(info);
		}
		if (pass_counter++ > VK32XX_ISR_PASS_LIMIT)
			break;
		sifr=vk3xxx_read_reg(port->iobase,VK32XX_SIFR);
		sier=vk3xxx_read_reg(port->iobase,VK32XX_SIER);//读取状态判断是哪里产生的中断。对vk32读取SIFR
		printk(KERN_ALERT "af rd sifr:%x sier:%x\n",sifr,sier);
	} while ((sifr & VK32XX_RFINT)||((sifr & VK32XX_TFINT)&&(sier & VK32XX_TRIEN)));
#ifdef _DEBUG_VK32XX
	printk(KERN_ALERT "sifr:%d\n",sifr);
#endif
}

/*
 * Return TIOCSER_TEMT when transmitter is not busy.
 */
static u_int vk32xx_tx_empty(struct uart_port *port)// or query the tx fifo is not empty?
{
	uint8_t	ssr;
#ifdef _DEBUG_VK32XX
	printk(KERN_ALERT "vk32xx_tx_empty\n");
#endif
	ssr=vk3xxx_read_reg(port->iobase,VK32XX_SSR);
	return ssr & VK32XX_TFEM ? 0 : TIOCSER_TEMT;
}

static u_int vk32xx_get_mctrl(struct uart_port *port)// since no modem control line
{
	return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
}

static void vk32xx_set_mctrl(struct uart_port *port, u_int mctrl)//nothing
{
}

/*
 * Interrupts always disabled.
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -