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

📄 serial_16550a.c

📁 这个vivi的功能很丰富
💻 C
字号:
#include "config.h"#include "machine.h"#include "serial_reg.h"#include "serial.h"#include "processor.h"#include <types.h>/* * This converts from our new CONFIG_ symbols to the symbols * that asm/serial.h expects.  You _NEED_ to comment out the * linux/config.h include contained inside asm/serial.h for * this to work. */#undef CONFIG_SERIAL_MANY_PORTS#undef CONFIG_SERIAL_DETECT_IRQ#undef CONFIG_SERIAL_MULTIPORT#undef CONFIG_HUB6#ifdef CONFIG_SERIAL_8250_MANY_PORTS#define CONFIG_SERIAL_MANY_PORTS 1#endif#ifdef CONFIG_SERIAL_8250_DETECT_IRQ#define CONFIG_SERIAL_DETECT_IRQ 1#endif#ifdef CONFIG_SERIAL_8250_MULTIPORT#define CONFIG_SERIAL_MULTIPORT 1#endif#ifdef CONFIG_SERIAL_8250_HUB6#define CONFIG_HUB6 1#endif#define SERIAL_DEBUG_AUTOCONF#include <asm/serial.h>/* UART16550A */#define EUART_CTL_BASE		0x10000000  //nGCS5//#define EUART_CTL_BASE		pSC16550A_IO_BASE  //nGCS2//#define EUART_CTL_BASE		0xd8000000//#define EUART0_CTL_BASE		EUART_CTL_BASE//#define EUART1_CTL_BASE		EUART_CTL_BASE + 0x08//#define EUART2_CTL_BASE		EUART_CTL_BASE + 0x10//#define EUART3_CTL_BASE		EUART_CTL_BASE + 0x18#define EUART0_CTL_BASE		0x10000000  //nGCS2#define EUART1_CTL_BASE		0x18000000  //nGCS3#define EUART2_CTL_BASE		0x20000000  //nGCS4#define EUART3_CTL_BASE		0x28000000  //nGCS5#define UART_NR	4 //4#define port_acr	unused[0]	/* 8bit */#define port_ier	unused[1]	/* 8bit */#define port_rev	unused[2]	/* 8bit */#define port_lcr	unused[3]	/* 8bit *//* * Here we define the default xmit fifo size used for each type of UART. */static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {	{ "unknown",	1,	0 },	{ "8250",	1,	0 },	{ "16450",	1,	0 },	{ "16550",	1,	0 },	{ "16550A",	16,	UART_CLEAR_FIFO | UART_USE_FIFO },	{ "Cirrus",	1, 	0 },	{ "ST16650",	1,	UART_CLEAR_FIFO | UART_STARTECH },	{ "ST16650V2",	32,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },	{ "TI16750",	64,	UART_CLEAR_FIFO | UART_USE_FIFO },	{ "Startech",	1,	0 },	{ "16C950/954",	128,	UART_CLEAR_FIFO | UART_USE_FIFO },	{ "ST16654",	64,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },	{ "XR16850",	128,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },	{ "RSA",	2048,	UART_CLEAR_FIFO | UART_USE_FIFO }};//#define GPIO_SERIAL#ifdef GPIO_SERIALstatic _INLINE_ unsigned intserial_in(struct uart_port *port, int offset){		//unsigned int ret;	unsigned char scratch, scratch1;	unsigned int addr;	unsigned long flags;	unsigned int mask;	    addr = offset&7;	switch(port->iobase)	{	case EUART0_CTL_BASE:	    mask = G16550_NGCS0_MASK;	    break;	case EUART1_CTL_BASE:	    //printk("Serial port 1 input,ioport=0x%08x\n",(port->iobase|0xC8000000) + offset);	    mask = G16550_NGCS1_MASK;	    break;	case EUART2_CTL_BASE:	    mask = G16550_NGCS2_MASK;	    break;	case EUART3_CTL_BASE:	default:	    //mask = 0;	    return 0;	}		spin_lock_irqsave(sio_lock,flags);    /* atomic IO */	GPCON(PORTD_OFS) = G16550_DBUS_DIR_IN | G16550_CBUS_DIR | G16550_ABUS_DIR;	GPDAT(PORTD_OFS) = (GPDAT(PORTD_OFS) & ~G16550_ADDR_MASK) | (addr << G16550_ADDR_SHIFT);	GPDAT(PORTD_OFS) = GPDAT(PORTD_OFS) & ~(mask|G16550_NREAD_MASK);	//GPDAT(PORTD_OFS) = GPDAT(PORTD_OFS) & ~G16550_NREAD_MASK;	scratch1 = GPDAT(PORTD_OFS) & G16550_DATA_MASK;	scratch = GPDAT(PORTD_OFS) & G16550_DATA_MASK;	//GPDAT(PORTD_OFS) = GPDAT(PORTD_OFS) | G16550_NREAD_MASK;	GPDAT(PORTD_OFS) = GPDAT(PORTD_OFS) | (mask|G16550_NREAD_MASK);	spin_unlock_irqrestore(sio_lock, flags);	//if (scratch == scratch1)	return scratch;	//else while(1);}static _INLINE_ voidserial_out(struct uart_port *port, int offset, unsigned int value){	//unsigned int ret;	int addr;	unsigned long flags;	unsigned int mask;		addr = offset&7;	switch(port->iobase)	{	case EUART0_CTL_BASE:	    mask = G16550_NGCS0_MASK;	    break;	case EUART1_CTL_BASE:	    //printk("Serial port 1 output,ioport=0x%08x\n",(port->iobase|0xC8000000) + offset);	    mask = G16550_NGCS1_MASK;	    break;	case EUART2_CTL_BASE:	    mask = G16550_NGCS2_MASK;	    break;	case EUART3_CTL_BASE:	default:	    //mask = 0;	    return;	}		spin_lock_irqsave(sio_lock, flags);	/* atomic IO */	GPCON(PORTD_OFS) = G16550_DBUS_DIR_OUT | G16550_CBUS_DIR | G16550_ABUS_DIR;	GPDAT(PORTD_OFS) = (GPDAT(PORTD_OFS) & (~G16550_DATA_MASK)) | (value&255);	GPDAT(PORTD_OFS) = (GPDAT(PORTD_OFS) & (~G16550_ADDR_MASK)) | (addr << G16550_ADDR_SHIFT);	GPDAT(PORTD_OFS) = GPDAT(PORTD_OFS) & ~(mask|G16550_NWRITE_MASK);	GPDAT(PORTD_OFS) = GPDAT(PORTD_OFS) & ~G16550_NWRITE_MASK;	//GPCON(PORTD_OFS) = G16550_DBUS_DIR_OUT | G16550_CBUS_DIR | G16550_ABUS_DIR;	//GPDAT(PORTD_OFS) = GPDAT(PORTD_OFS) | G16550_NWRITE_MASK;	GPDAT(PORTD_OFS) = GPDAT(PORTD_OFS) | (mask|G16550_NWRITE_MASK);	GPCON(PORTD_OFS) = G16550_DBUS_DIR_IN | G16550_CBUS_DIR | G16550_ABUS_DIR;	spin_unlock_irqrestore(sio_lock, flags);}#elsestatic inline unsigned charserial_in(struct uart_port *port, int reg){	//udelay(10);	return *(volatile unsigned char *)(port->iobase + reg);}static inline voidserial_out(struct uart_port *port, int reg, unsigned int value){	//udelay(10);	*(volatile unsigned char *)(port->iobase + reg) = value;}#endif/* * We used to support using pause I/O for certain machines.  We * haven't supported this for a while, but just in case it's badly * needed for certain old 386 machines, I've left these #define's * in.... */#define serial_inp(port, reg)		serial_in(port, reg)#define serial_outp(port, reg, value)	serial_out(port, reg, value)/* * This is a quickie test to see how big the FIFO is. * It doesn't work at all the time, more's the pity. */static int size_fifo(struct uart_port *port){	unsigned char old_fcr, old_mcr, old_dll, old_dlm;	int count;	old_fcr = serial_inp(port, UART_FCR);	old_mcr = serial_inp(port, UART_MCR);	//serial_outp(port, UART_FCR, UART_FCR_ENABLE_FIFO);	serial_outp(port, UART_FCR, UART_FCR_ENABLE_FIFO |		    UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);	serial_outp(port, UART_MCR, UART_MCR_LOOP);	serial_outp(port, UART_LCR, UART_LCR_DLAB);	old_dll = serial_inp(port, UART_DLL);	old_dlm = serial_inp(port, UART_DLM);	serial_outp(port, UART_DLL, 0x01);	serial_outp(port, UART_DLM, 0x00);	serial_outp(port, UART_LCR, UART_LCR_WLEN8);	for (count = 0; count < 256; count++)		serial_outp(port, UART_TX, count);		do{	    mdelay(20);    }while((!(serial_inp(port, UART_LSR) & UART_LSR_THRE)) && count--);	for (count = 0; (serial_inp(port, UART_LSR) & UART_LSR_DR) && (count < 256); count++)		serial_inp(port, UART_RX);	serial_outp(port, UART_FCR, old_fcr);	serial_outp(port, UART_MCR, old_mcr);	serial_outp(port, UART_LCR, UART_LCR_DLAB);	serial_outp(port, UART_DLL, old_dll);	serial_outp(port, UART_DLM, old_dlm);	printk("autoconfig: fifosize is %d byte(s).\n",count);	return count;}/* * This routine is called by rs_init() to initialize a specific serial * port.  It determines what type of UART chip this serial port is * using: 8250, 16450, 16550, 16550A.  The important question is * whether or not this UART is a 16550A or not, since this will * determine whether or not we can use its FIFO features or not. */static int autoconfig(struct uart_port *port, unsigned int probeflags){	unsigned char status1, status2, scratch, scratch2, scratch3;	unsigned char save_lcr, save_mcr;	unsigned long flags;#ifdef SERIAL_DEBUG_AUTOCONF	printk("Testing ttyS%d (0x%04x, 0x%08lx)...\n",		port->line, port->iobase, port->membase);#endif	if (!port->iobase)		return -1;	if (!(port->flags & ASYNC_BUGGY_UART)) {		/*		 * Do a simple existence test first; if we fail this,		 * there's no point trying anything else.		 * 		 * 0x80 is used as a nonsense port to prevent against		 * false positives due to ISA bus float.  The		 * assumption is that 0x80 is a non-existent port;		 * which should be safe since include/asm/io.h also		 * makes this assumption.		 */		scratch = serial_inp(port, UART_IER);		serial_outp(port, UART_IER, 0);		scratch2 = serial_inp(port, UART_IER);		serial_outp(port, UART_IER, 0x0F);		scratch3 = serial_inp(port, UART_IER);		serial_outp(port, UART_IER, scratch);		if (scratch2 || scratch3 != 0x0F) {#ifdef SERIAL_DEBUG_AUTOCONF			printk("serial: ttyS%d: simple autoconfig failed "			       "(%02x, %02x)\n", port->line, 			       scratch2, scratch3);#endif			return -1;		/* We failed; there's nothing here */		}	}	save_mcr = serial_in(port, UART_MCR);	save_lcr = serial_in(port, UART_LCR);	/* 	 * Check to see if a UART is really there.  Certain broken	 * internal modems based on the Rockwell chipset fail this	 * test, because they apparently don't implement the loopback	 * test mode.  So this test is skipped on the COM 1 through	 * COM 4 ports.  This *should* be safe, since no board	 * manufacturer would be stupid enough to design a board	 * that conflicts with COM 1-4 --- we hope!	 */	if (!(port->flags & ASYNC_SKIP_TEST)) {		serial_outp(port, UART_MCR, UART_MCR_LOOP | 0x0A);		status1 = serial_inp(port, UART_MSR) & 0xF0;		serial_outp(port, UART_MCR, save_mcr);		if (status1 != 0x90) {#ifdef SERIAL_DEBUG_AUTOCONF			printk("serial: ttyS%d: no UART loopback failed\n",			       port->line);#endif			return -1;		}	}		serial_outp(port, UART_LCR, 0xBF); /* set up for StarTech test */	serial_outp(port, UART_EFR, 0);	/* EFR is the same as FCR */	serial_outp(port, UART_LCR, 0);	serial_outp(port, UART_FCR, UART_FCR_ENABLE_FIFO);	scratch = serial_in(port, UART_IIR) >> 6;	switch (scratch) {		case 0:			port->type = PORT_16450;			printk("Found Serial Port PORT_16450!\n");			break;		case 1:			port->type = PORT_UNKNOWN;			printk("Found Serial Port PORT_UNKNOWN!\n");			break;		case 2:			port->type = PORT_16550;			printk("Found Serial Port PORT_16550!\n");			break;		case 3:			port->type = PORT_16550A;			printk("Found Serial Port PORT_16550A!\n");			break;	}	if (port->type == PORT_16550A) {		/* Check for Startech UART's */		serial_outp(port, UART_LCR, UART_LCR_DLAB);		if (serial_in(port, UART_EFR) == 0) {			port->type = PORT_16650;		} else {			serial_outp(port, UART_LCR, 0xBF);			if (serial_in(port, UART_EFR) == 0)				;		}	}#if 0	if (port->type == PORT_16550A) {		/* Check for TI 16750 */		serial_outp(port, UART_LCR, save_lcr | UART_LCR_DLAB);		serial_outp(port, UART_FCR,			    UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);		scratch = serial_in(port, UART_IIR) >> 5;		if (scratch == 7) {			/*			 * If this is a 16750, and not a cheap UART			 * clone, then it should only go into 64 byte			 * mode if the UART_FCR7_64BYTE bit was set			 * while UART_LCR_DLAB was latched.			 */ 			serial_outp(port, UART_FCR, UART_FCR_ENABLE_FIFO);			serial_outp(port, UART_LCR, 0);			serial_outp(port, UART_FCR,				    UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);			scratch = serial_in(port, UART_IIR) >> 5;			if (scratch == 6)				port->type = PORT_16750;		}		serial_outp(port, UART_FCR, UART_FCR_ENABLE_FIFO);	}#endif	serial_outp(port, UART_LCR, save_lcr);	if (port->type == PORT_16450) {		scratch = serial_in(port, UART_SCR);		serial_outp(port, UART_SCR, 0xa5);		status1 = serial_in(port, UART_SCR);		serial_outp(port, UART_SCR, 0x5a);		status2 = serial_in(port, UART_SCR);		serial_outp(port, UART_SCR, scratch);		if ((status1 != 0xa5) || (status2 != 0x5a))			port->type = PORT_8250;	}	port->fifosize = size_fifo(port); //uart_config[port->type].dfl_xmit_fifo_size;	if (port->type == PORT_UNKNOWN) {		return -1;	}	/*	 * Reset the UART.	 */	serial_outp(port, UART_MCR, save_mcr);	serial_outp(port, UART_FCR, (UART_FCR_ENABLE_FIFO |				     UART_FCR_CLEAR_RCVR |				     UART_FCR_CLEAR_XMIT));	serial_outp(port, UART_FCR, 0);	(void)serial_in(port, UART_RX);	serial_outp(port, UART_IER, 0);	return 0;}//static struct uart_port serial8250_ports[UART_NR];static struct uart_port serial8250_ports[4] = {  {	iobase:		(unsigned long)(EUART0_CTL_BASE),	iotype:		SERIAL_IO_PORT,	uartclk:	1843200,	fifosize:	16,	type:		PORT_16550A,	flags:		ASYNC_BOOT_AUTOCONF,  }, {	iobase:		(unsigned long)(EUART1_CTL_BASE),	iotype:		SERIAL_IO_PORT,	uartclk:	1843200,	fifosize:	16,	type:		PORT_16550A,	flags:		ASYNC_BOOT_AUTOCONF,  }, {	iobase:		(unsigned long)(EUART2_CTL_BASE),	iotype:		SERIAL_IO_PORT,	uartclk:	1843200,	fifosize:	16,	type:		PORT_16550A,	flags:		ASYNC_BOOT_AUTOCONF,  }, {	iobase:		(unsigned long)(EUART3_CTL_BASE),	iotype:		SERIAL_IO_PORT,	uartclk:	1843200,	fifosize:	16,	type:		PORT_16550A,	flags:		ASYNC_BOOT_AUTOCONF,  }};int Serial16550A_init(void){    int i;        if (autoconfig(&serial8250_ports[0], 0)<0)        printk("no 16C550 serial port found!\n");    autoconfig(&serial8250_ports[1], 0);    autoconfig(&serial8250_ports[2], 0);    autoconfig(&serial8250_ports[3], 0);    /*for (i=0;i<6;i++) {        printk("%d",i+1);        mdelay(1000);    }printk("\n");*/    return 0;}

⌨️ 快捷键说明

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