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

📄 tl16c554_linux.c

📁 TL16C554在Linux2.4.18下的可运行驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * tl16c554.c * * TL16C554 driver for SAMSUNG S3C2410 * * Author: Yongping wu <godiscrazy@163.com> * Date  : $Date: 2006/03/14 16:13:04 $ * * $Revision: 1.1V $ *TL16C554APN3.6864mhz扩展芯片:2*TL16C554APN可为系统增加8个串口,直接与S3C2410总线连接,8位数据宽度地址空间:占用系统BANK5地址从前到后分别对应每个UART0-7个寄存器UART0A:0x2800_0000---0x2800_0003;0x2880_0000---0x2880_0003						A2A1A0(TL16C554)		0x2800_0000     0 0 0		0x2800_0001     0 0 1		0x2800_0002     0 1 0		0x2800_0003     0 1 1		0x2880_0000     1 0 0		0x2880_0001     1 0 1		0x2880_0002     1 1 0		0x2880_0003     1 1 1UART0B:0x2800_2000---0x2800_2003;0x2880_2000---0x2880_2003UART0C:0x2800_4000---0x2800_4003;0x2880_4000---0x2880_4003UART0D:0x2800_6000---0x2800_6003;0x2880_6000---0x2880_6003UART1A:0x2800_8000---0x2800_8003;0x2880_8000---0x2880_8003UART1B:0x2800_A000---0x2800_A003;0x2880_A000---0x2880_A003UART1C:0x2800_C000---0x2800_C003;0x2880_C000---0x2880_C003UART1D:0x2800_E000---0x2800_E003;0x2880_E000---0x2880_E003控制寄存器Line-control register(LCR)0x03FIFO-control register(FCR)0x02Modem-control register(MCR)0x04Divisor-latch LSB(DLL)LCR(bit7=1)0x00Divisor-latch MSB(DLM)LCR(bit7=1)0x01Interrupt enable register(IER)0x01状态寄存器Line-status register(LSR)0x05Modem-status register(MSR)0x06数据寄存器Receiver-buffer register(RBR)0x00Transmitter-holding register(THR)0x00 */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <asm/arch/S3C2410.h>#include <asm/arch/cpu_s3c2410.h>#include <asm/hardware.h>#include <asm/io.h>#define TL0_A_READ	0#define TL0_B_READ	1#define TL0_C_READ	2#define TL0_D_READ	3#define TL1_A_READ	4#define TL1_B_READ	5#define TL1_C_READ	6#define TL1_D_READ	7#define TL0_A_WRITE	8#define TL0_B_WRITE	9#define TL0_C_WRITE	10#define TL0_D_WRITE	11#define TL1_A_WRITE	12#define TL1_B_WRITE	13#define TL1_C_WRITE	14#define TL1_D_WRITE	15#define TL_INIT	32#define GPG2ON	33#define GPG2OFF	34typedef struct tagTL_INIT{	int nChn;	int nBaud;	unsigned char byMode;} myTL_INIT;myTL_INIT tl0A_init;myTL_INIT tl0B_init;myTL_INIT tl0C_init;myTL_INIT tl0D_init;#define NONEPARITY	0x00#define ODDPARITY	0x08#define EVENPARITY	0x18#define DATA7BIT	0x80#define BAUDBASE	0x30					/***4800bps->hex***/#define TL_COM_CNT	8#define TL_RECV_LEN	1600#define TL_SEND_LEN	160typedef struct {	int nAddress0;	int nAddress1;	int sInited;	unsigned char *pbyBase0;	unsigned char *pbyBase1;		//数据寄存器	int RBR;//Receiver-buffer register				0	int THR;//Transmitter-holding register			0		//状态寄存器	int LSR;//Line-status register					5	int MSR;//Modem-status register					6		//控制寄存器	int LCR;//Line-control register					3	int FCR;//FIFO-control register					2	int MCR;//Modem-control register				4	int DLL;//Divisor-latch LSB						0	int DLM;//Divisor-latch MSB						1	int IER;//Interrupt enable register				1		//其它寄存器	int SPR;//Scratchpad register					7	int IIR;//Interrupt identification register		2		//串口数据接收缓冲区	volatile short sRecvHead;	volatile short sRecvTail;	volatile unsigned char abyRecvData[TL_RECV_LEN];		//串口数据发送缓冲区	volatile short sSendHead;	volatile short sSendTail;	volatile unsigned char abySendData[TL_SEND_LEN];	} TL_COM;static TL_COM tl0A = {0x28000000,0x28800000,0};static TL_COM tl0B = {0x28002000,0x28802000,0};static TL_COM tl0C = {0x28004000,0x28804000,0};static TL_COM tl0D = {0x28006000,0x28806000,0};#define DEVICE_NAME	"TL16C554"#define DEVICE_MAJOR 233#define TL0A	0#define TL0B	1#define TL0C	2#define TL0D	3static int tlMajor = 233;inline int get_TL0A_rxLen(void){	if(tl0A.sRecvHead==tl0A.sRecvTail){		return 0;	}	else if(tl0A.sRecvTail>tl0A.sRecvHead){		return (tl0A.sRecvTail-tl0A.sRecvHead);	}	else{		return ( TL_RECV_LEN-(tl0A.sRecvHead-tl0A.sRecvTail) );	}}inline int get_TL0B_rxLen(void){	if(tl0B.sRecvHead==tl0B.sRecvTail){		return 0;	}	else if(tl0B.sRecvTail>tl0B.sRecvHead){		return (tl0B.sRecvTail-tl0B.sRecvHead);	}	else{		return ( TL_RECV_LEN-(tl0B.sRecvHead-tl0B.sRecvTail) );	}}inline int get_TL0C_rxLen(void){	if(tl0C.sRecvHead==tl0C.sRecvTail){		return 0;	}	else if(tl0C.sRecvTail>tl0C.sRecvHead){		return (tl0C.sRecvTail-tl0C.sRecvHead);	}	else{		return ( TL_RECV_LEN-(tl0C.sRecvHead-tl0C.sRecvTail) );	}}inline int get_TL0D_rxLen(void){	if(tl0D.sRecvHead==tl0D.sRecvTail){		return 0;	}	else if(tl0D.sRecvTail>tl0D.sRecvHead){		return (tl0D.sRecvTail-tl0D.sRecvHead);	}	else{		return ( TL_RECV_LEN-(tl0D.sRecvHead-tl0D.sRecvTail) );	}}inline int get_TL0A_txLen(void){	if(tl0A.sSendHead==tl0A.sSendTail){		return 0;	}	else if(tl0A.sSendTail>tl0A.sSendHead){		return (tl0A.sSendTail-tl0A.sSendHead);	}	else{		return ( TL_SEND_LEN-(tl0A.sSendHead-tl0A.sSendTail) );	}}inline int get_TL0B_txLen(void){	if(tl0B.sSendHead==tl0B.sSendTail){		return 0;	}	else if(tl0B.sSendTail>tl0B.sSendHead){		return (tl0B.sSendTail-tl0B.sSendHead);	}	else{		return ( TL_SEND_LEN-(tl0B.sSendHead-tl0B.sSendTail) );	}}inline int get_TL0C_txLen(void){	if(tl0C.sSendHead==tl0C.sSendTail){		return 0;	}	else if(tl0C.sSendTail>tl0C.sSendHead){		return (tl0C.sSendTail-tl0C.sSendHead);	}	else{		return ( TL_SEND_LEN-(tl0C.sSendHead-tl0C.sSendTail) );	}}inline int get_TL0D_txLen(void){	if(tl0D.sSendHead==tl0D.sSendTail){		return 0;	}	else if(tl0D.sSendTail>tl0D.sSendHead){		return (tl0D.sSendTail-tl0D.sSendHead);	}	else{		return ( TL_SEND_LEN-(tl0D.sSendHead-tl0D.sSendTail) );	}}inline char tl0aIsEmpty_rx(void){	return (tl0A.sRecvHead==tl0A.sRecvTail ? 1 : 0);}inline char tl0bIsEmpty_rx(void){	return (tl0B.sRecvHead==tl0B.sRecvTail ? 1 : 0);}inline char tl0cIsEmpty_rx(void){	return (tl0C.sRecvHead==tl0C.sRecvTail ? 1 : 0);}inline char tl0dIsEmpty_rx(void){	return (tl0D.sRecvHead==tl0D.sRecvTail ? 1 : 0);}inline char tl0aIsFull_rx(void){	return (tl0A.sRecvHead==(tl0A.sRecvTail+1)%TL_RECV_LEN ? 1 : 0);}inline char tl0bIsFull_rx(void){	return (tl0B.sRecvHead==(tl0B.sRecvTail+1)%TL_RECV_LEN ? 1 : 0);}inline char tl0cIsFull_rx(void){	return (tl0C.sRecvHead==(tl0C.sRecvTail+1)%TL_RECV_LEN ? 1 : 0);}inline char tl0dIsFull_rx(void){	return (tl0D.sRecvHead==(tl0D.sRecvTail+1)%TL_RECV_LEN ? 1 : 0);}inline char tl0aIsEmpty_tx(void){	return (tl0A.sSendHead==tl0A.sSendTail ? 1 : 0);}inline char tl0bIsEmpty_tx(void){	return (tl0B.sSendHead==tl0B.sSendTail ? 1 : 0);}inline char tl0cIsEmpty_tx(void){	return (tl0C.sSendHead==tl0C.sSendTail ? 1 : 0);}inline char tl0dIsEmpty_tx(void){	return (tl0D.sSendHead==tl0D.sSendTail ? 1 : 0);}inline char tl0aIsFull_tx(void){	return (tl0A.sSendHead==(tl0A.sSendTail+1)%TL_SEND_LEN ? 1 : 0);}inline char tl0bIsFull_tx(void){	return (tl0B.sSendHead==(tl0B.sSendTail+1)%TL_SEND_LEN ? 1 : 0);}inline char tl0cIsFull_tx(void){	return (tl0C.sSendHead==(tl0C.sSendTail+1)%TL_SEND_LEN ? 1 : 0);}inline char tl0dIsFull_tx(void){	return (tl0D.sSendHead==(tl0D.sSendTail+1)%TL_SEND_LEN ? 1 : 0);}inline void pushTL0ARX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	tl0A.abyRecvData[tl0A.sRecvTail] = byRx;	if(!tl0aIsFull_rx()){		tl0A.sRecvTail++;		tl0A.sRecvTail %= TL_RECV_LEN;	}}inline void pushTL0BRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	tl0B.abyRecvData[tl0B.sRecvTail] = byRx;	if(!tl0bIsFull_rx()){		tl0B.sRecvTail++;		tl0B.sRecvTail %= TL_RECV_LEN;	}}inline void pushTL0CRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	tl0C.abyRecvData[tl0C.sRecvTail] = byRx;	if(!tl0cIsFull_rx()){		tl0C.sRecvTail++;		tl0C.sRecvTail %= TL_RECV_LEN;	}}inline void pushTL0DRX(unsigned char byRx){//缓冲区满时, 最后一个接收数据放在最后一个位置	tl0D.abyRecvData[tl0D.sRecvTail] = byRx;	if(!tl0dIsFull_rx()){		tl0D.sRecvTail++;		tl0D.sRecvTail %= TL_RECV_LEN;	}}inline unsigned char tl0apopRX(void){//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据	unsigned char byRet;	byRet = tl0A.abyRecvData[tl0A.sRecvHead];	if(!tl0aIsEmpty_rx()){		tl0A.sRecvHead++;		tl0A.sRecvHead %= TL_RECV_LEN;	}	return byRet;}inline unsigned char tl0bpopRX(void){//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据	unsigned char byRet;	byRet = tl0B.abyRecvData[tl0B.sRecvHead];	if(!tl0bIsEmpty_rx()){		tl0B.sRecvHead++;		tl0B.sRecvHead %= TL_RECV_LEN;	}	return byRet;}inline unsigned char tl0cpopRX(void){//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据	unsigned char byRet;	byRet = tl0C.abyRecvData[tl0C.sRecvHead];	if(!tl0cIsEmpty_rx()){		tl0C.sRecvHead++;		tl0C.sRecvHead %= TL_RECV_LEN;	}	return byRet;}inline unsigned char tl0dpopRX(void){//为空时返回最后接收到的一个数据,从未接收到数据时返回缓冲区第一个字节数据	unsigned char byRet;	byRet = tl0D.abyRecvData[tl0D.sRecvHead];	if(!tl0dIsEmpty_rx()){		tl0D.sRecvHead++;		tl0D.sRecvHead %= TL_RECV_LEN;	}	return byRet;}//TL16C554初始化void Init_TL0A(int nBaud, unsigned char byMode){	volatile unsigned char byRx;	int i;		if(0 != tl0A.sInited){		iounmap((void *) (tl0A.pbyBase0));		iounmap((void *) (tl0A.pbyBase1));	}	tl0A.pbyBase0 = (unsigned char *)ioremap_nocache(tl0A.nAddress0, 4);	tl0A.pbyBase1 = (unsigned char *)ioremap_nocache(tl0A.nAddress1, 4);		tl0A.RBR = (int)(tl0A.pbyBase0);	tl0A.THR = (int)(tl0A.pbyBase0);	tl0A.LSR = (int)(tl0A.pbyBase1+1);	tl0A.MSR = (int)(tl0A.pbyBase1+2);	tl0A.LCR = (int)(tl0A.pbyBase0+3);	tl0A.FCR = (int)(tl0A.pbyBase0+2);	tl0A.MCR = (int)(tl0A.pbyBase1);	tl0A.DLL = (int)(tl0A.pbyBase0);	tl0A.DLM = (int)(tl0A.pbyBase0+1);	tl0A.IER = (int)(tl0A.pbyBase0+1);	tl0A.SPR = (int)(tl0A.pbyBase1+3);	tl0A.IIR = (int)(tl0A.pbyBase0+2);		tl0A.sRecvHead = 0;	tl0A.sRecvTail = 0;	tl0A.sSendHead = 0;	tl0A.sSendTail = 0;		//IER	//接收保持和中断允许	*(volatile unsigned char *)(tl0A.IER) = 0x01;//0x05;		//FIFO控制器	//set FCR.FIFO允许,RXD复位,TXD复位,DMAmode=1,触发为14	*(volatile unsigned char *)(tl0A.FCR) = 0xcf;	for(i=0; i<100; i++);	//set FCR.RXD复位,TXD复位	*(volatile unsigned char *)(tl0A.FCR) = 0xc9;		//Modem状态	//set MCR.中断A-D开	*(volatile unsigned char *)(tl0A.MCR) = 0x08;		if(byMode&0x80){		*(volatile unsigned char *)(tl0A.LCR) = 0x82|(byMode&0x7f);//7 bit

⌨️ 快捷键说明

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