serial.c

来自「OMAP2530 uboot source code」· C语言 代码 · 共 1,082 行 · 第 1/3 页

C
1,082
字号
/*#define asyncTxBufferport1      ACTING_UART0_BASE+0x00 *//*#define asyncRxBufferport1      ACTING_UART0_BASE+0x00 */#ifdef CONFIG_SERIAL_SOFTWARE_FIFO/*-----------------------------------------------------------------------------+  | Fifo  +-----------------------------------------------------------------------------*/typedef struct {	char *rx_buffer;	ulong rx_put;	ulong rx_get;} serial_buffer_t;volatile static serial_buffer_t buf_info;#endif#if defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLOCK)static void serial_divs (int baudrate, unsigned long *pudiv,			 unsigned short *pbdiv ){	sys_info_t	sysinfo;	unsigned long div;		/* total divisor udiv * bdiv */	unsigned long umin;		/* minimum udiv	*/	unsigned short diff;    /* smallest diff */	unsigned long udiv;     /* best udiv */	unsigned short idiff;   /* current diff */	unsigned short ibdiv;   /* current bdiv */	unsigned long i;	unsigned long est;      /* current estimate */	get_sys_info( &sysinfo );	udiv = 32;     /* Assume lowest possible serial clk */	div = sysinfo.freqPLB/(16*baudrate); /* total divisor */	umin = sysinfo.pllOpbDiv<<1; /* 2 x OPB divisor */	diff = 32;      /* highest possible */	/* i is the test udiv value -- start with the largest	 * possible (32) to minimize serial clock and constrain	 * search to umin.	 */	for( i = 32; i > umin; i-- ){		ibdiv = div/i;		est = i * ibdiv;		idiff = (est > div) ? (est-div) : (div-est);		if( idiff == 0 ){			udiv = i;			break;      /* can't do better */		}		else if( idiff < diff ){			udiv = i;       /* best so far */			diff = idiff;   /* update lowest diff*/		}	}	*pudiv = udiv;	*pbdiv = div/udiv;}#endif /* defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLK *//* * Minimal serial functions needed to use one of the SMC ports * as serial console interface. */#if defined(CONFIG_440)#if defined(CONFIG_SERIAL_MULTI)int serial_init_dev (unsigned long dev_base)#elseint serial_init(void)#endif{	unsigned long reg;	unsigned long udiv;	unsigned short bdiv;	volatile char val;#ifdef CFG_EXT_SERIAL_CLOCK	unsigned long tmp;#endif#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || \	defined(CONFIG_440SPE)#if defined(CONFIG_SERIAL_MULTI)	if (UART0_BASE == dev_base) {		mfsdr(UART0_SDR,reg);		reg &= ~CR0_MASK;	} else {		mfsdr(UART1_SDR,reg);		reg &= ~CR0_MASK;	}#else	mfsdr(UART0_SDR,reg);	reg &= ~CR0_MASK;#endif#else	reg = mfdcr(cntrl0) & ~CR0_MASK;#endif /* CONFIG_440GX */#ifdef CFG_EXT_SERIAL_CLOCK	reg |= CR0_EXTCLK_ENA;	udiv = 1;	tmp  = gd->baudrate * 16;	bdiv = (CFG_EXT_SERIAL_CLOCK + tmp / 2) / tmp;#else	/* For 440, the cpu clock is on divider chain A, UART on divider	 * chain B ... so cpu clock is irrelevant. Get the "optimized"	 * values that are subject to the 1/2 opb clock constraint	 */	serial_divs (gd->baudrate, &udiv, &bdiv);#endif#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \	defined(CONFIG_440GR) || defined(CONFIG_440SP) || \	defined(CONFIG_440SPE)	reg |= udiv << CR0_UDIV_POS;	/* set the UART divisor */#if defined(CONFIG_SERIAL_MULTI)	if (UART0_BASE == dev_base) {		mtsdr (UART0_SDR,reg);	} else {		mtsdr (UART1_SDR,reg);	}#else	mtsdr (UART0_SDR,reg);#endif#else	reg |= (udiv - 1) << CR0_UDIV_POS;	/* set the UART divisor */	mtdcr (cntrl0, reg);#endif#if defined(CONFIG_SERIAL_MULTI)	out8 (dev_base + UART_LCR, 0x80);	/* set DLAB bit */	out8 (dev_base + UART_DLL, bdiv);	/* set baudrate divisor */	out8 (dev_base + UART_DLM, bdiv >> 8);/* set baudrate divisor */	out8 (dev_base + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */	out8 (dev_base + UART_FCR, 0x00);	/* disable FIFO */	out8 (dev_base + UART_MCR, 0x00);	/* no modem control DTR RTS */	val = in8 (dev_base + UART_LSR);	/* clear line status */	val = in8 (dev_base + UART_RBR);	/* read receive buffer */	out8 (dev_base + UART_SCR, 0x00);	/* set scratchpad */	out8 (dev_base + UART_IER, 0x00);	/* set interrupt enable reg */#else	out8 (ACTING_UART0_BASE + UART_LCR, 0x80);	/* set DLAB bit */	out8 (ACTING_UART0_BASE + UART_DLL, bdiv);	/* set baudrate divisor */	out8 (ACTING_UART0_BASE + UART_DLM, bdiv >> 8);/* set baudrate divisor */	out8 (ACTING_UART0_BASE + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */	out8 (ACTING_UART0_BASE + UART_FCR, 0x00);	/* disable FIFO */	out8 (ACTING_UART0_BASE + UART_MCR, 0x00);	/* no modem control DTR RTS */	val = in8 (ACTING_UART0_BASE + UART_LSR);	/* clear line status */	val = in8 (ACTING_UART0_BASE + UART_RBR);	/* read receive buffer */	out8 (ACTING_UART0_BASE + UART_SCR, 0x00);	/* set scratchpad */	out8 (ACTING_UART0_BASE + UART_IER, 0x00);	/* set interrupt enable reg */#endif	return (0);}#else /* !defined(CONFIG_440) */#if defined(CONFIG_SERIAL_MULTI)int serial_init_dev (unsigned long dev_base)#elseint serial_init (void)#endif{	unsigned long reg;	unsigned long tmp;	unsigned long clk;	unsigned long udiv;	unsigned short bdiv;	volatile char val;#ifdef CONFIG_405EP	reg = mfdcr(cpc0_ucr) & ~(UCR0_MASK | UCR1_MASK);	clk = gd->cpu_clk;	tmp = CFG_BASE_BAUD * 16;	udiv = (clk + tmp / 2) / tmp;	if (udiv > UDIV_MAX)                    /* max. n bits for udiv */		udiv = UDIV_MAX;	reg |= (udiv) << UCR0_UDIV_POS;	        /* set the UART divisor */	reg |= (udiv) << UCR1_UDIV_POS;	        /* set the UART divisor */	mtdcr (cpc0_ucr, reg);#else /* CONFIG_405EP */	reg = mfdcr(cntrl0) & ~CR0_MASK;#ifdef CFG_EXT_SERIAL_CLOCK	clk = CFG_EXT_SERIAL_CLOCK;	udiv = 1;	reg |= CR0_EXTCLK_ENA;#else	clk = gd->cpu_clk;#ifdef CFG_405_UART_ERRATA_59	udiv = 31;			/* Errata 59: stuck at 31 */#else	tmp = CFG_BASE_BAUD * 16;	udiv = (clk + tmp / 2) / tmp;	if (udiv > UDIV_MAX)                    /* max. n bits for udiv */		udiv = UDIV_MAX;#endif#endif	reg |= (udiv - 1) << CR0_UDIV_POS;	/* set the UART divisor */	mtdcr (cntrl0, reg);#endif /* CONFIG_405EP */	tmp = gd->baudrate * udiv * 16;	bdiv = (clk + tmp / 2) / tmp;#if defined(CONFIG_SERIAL_MULTI)	out8 (dev_base + UART_LCR, 0x80);	/* set DLAB bit */	out8 (dev_base + UART_DLL, bdiv);	/* set baudrate divisor */	out8 (dev_base + UART_DLM, bdiv >> 8);/* set baudrate divisor */	out8 (dev_base + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */	out8 (dev_base + UART_FCR, 0x00);	/* disable FIFO */	out8 (dev_base + UART_MCR, 0x00);	/* no modem control DTR RTS */	val = in8 (dev_base + UART_LSR);	/* clear line status */	val = in8 (dev_base + UART_RBR);	/* read receive buffer */	out8 (dev_base + UART_SCR, 0x00);	/* set scratchpad */	out8 (dev_base + UART_IER, 0x00);	/* set interrupt enable reg */#else	out8 (ACTING_UART0_BASE + UART_LCR, 0x80);	/* set DLAB bit */	out8 (ACTING_UART0_BASE + UART_DLL, bdiv);	/* set baudrate divisor */	out8 (ACTING_UART0_BASE + UART_DLM, bdiv >> 8);/* set baudrate divisor */	out8 (ACTING_UART0_BASE + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */	out8 (ACTING_UART0_BASE + UART_FCR, 0x00);	/* disable FIFO */	out8 (ACTING_UART0_BASE + UART_MCR, 0x00);	/* no modem control DTR RTS */	val = in8 (ACTING_UART0_BASE + UART_LSR);	/* clear line status */	val = in8 (ACTING_UART0_BASE + UART_RBR);	/* read receive buffer */	out8 (ACTING_UART0_BASE + UART_SCR, 0x00);	/* set scratchpad */	out8 (ACTING_UART0_BASE + UART_IER, 0x00);	/* set interrupt enable reg */#endif	return (0);}#endif /* if defined(CONFIG_440) */#if defined(CONFIG_SERIAL_MULTI)void serial_setbrg_dev (unsigned long dev_base)#elsevoid serial_setbrg (void)#endif{	unsigned long tmp;	unsigned long clk;	unsigned long udiv;	unsigned short bdiv;#ifdef CFG_EXT_SERIAL_CLOCK	clk = CFG_EXT_SERIAL_CLOCK;#else	clk = gd->cpu_clk;#endif#ifdef CONFIG_405EP	udiv = ((mfdcr (cpc0_ucr) & UCR0_MASK) >> UCR0_UDIV_POS);#else	udiv = ((mfdcr (cntrl0) & 0x3e) >> 1) + 1;#endif /* CONFIG_405EP */#if !defined(CFG_EXT_SERIAL_CLOCK) && \	( defined(CONFIG_440GX) || defined(CONFIG_440EP) || \	  defined(CONFIG_440GR) || defined(CONFIG_440SP) || \	  defined(CONFIG_440SPE) )	serial_divs (gd->baudrate, &udiv, &bdiv);	tmp = udiv << CR0_UDIV_POS;		/* set the UART divisor */#if defined(CONFIG_SERIAL_MULTI)	if (UART0_BASE == dev_base) {		mtsdr (UART0_SDR, tmp);	} else {		mtsdr (UART1_SDR, tmp);	}#else	mtsdr (UART0_SDR, tmp);#endif#else	tmp = gd->baudrate * udiv * 16;	bdiv = (clk + tmp / 2) / tmp;#endif /* !defined(CFG_EXT_SERIAL_CLOCK) && (...) */#if defined(CONFIG_SERIAL_MULTI)	out8 (dev_base + UART_LCR, 0x80);	/* set DLAB bit */	out8 (dev_base + UART_DLL, bdiv);	/* set baudrate divisor */	out8 (dev_base + UART_DLM, bdiv >> 8);/* set baudrate divisor */	out8 (dev_base + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */#else	out8 (ACTING_UART0_BASE + UART_LCR, 0x80);	/* set DLAB bit */	out8 (ACTING_UART0_BASE + UART_DLL, bdiv);	/* set baudrate divisor */	out8 (ACTING_UART0_BASE + UART_DLM, bdiv >> 8);/* set baudrate divisor */	out8 (ACTING_UART0_BASE + UART_LCR, 0x03);	/* clear DLAB; set 8 bits, no parity */#endif}#if defined(CONFIG_SERIAL_MULTI)void serial_putc_dev (unsigned long dev_base, const char c)#elsevoid serial_putc (const char c)#endif{	int i;	if (c == '\n')#if defined(CONFIG_SERIAL_MULTI)		serial_putc_dev (dev_base, '\r');#else		serial_putc ('\r');#endif	/* check THRE bit, wait for transmiter available */	for (i = 1; i < 3500; i++) {#if defined(CONFIG_SERIAL_MULTI)		if ((in8 (dev_base + UART_LSR) & 0x20) == 0x20)#else		if ((in8 (ACTING_UART0_BASE + UART_LSR) & 0x20) == 0x20)#endif			break;		udelay (100);	}#if defined(CONFIG_SERIAL_MULTI)	out8 (dev_base + UART_THR, c);	/* put character out */#else	out8 (ACTING_UART0_BASE + UART_THR, c);	/* put character out */#endif}#if defined(CONFIG_SERIAL_MULTI)void serial_puts_dev (unsigned long dev_base, const char *s)#elsevoid serial_puts (const char *s)#endif{	while (*s) {#if defined(CONFIG_SERIAL_MULTI)		serial_putc_dev (dev_base, *s++);#else		serial_putc (*s++);#endif	}}#if defined(CONFIG_SERIAL_MULTI)int serial_getc_dev (unsigned long dev_base)#elseint serial_getc (void)#endif{	unsigned char status = 0;	while (1) {#if defined(CONFIG_HW_WATCHDOG)		WATCHDOG_RESET ();	/* Reset HW Watchdog, if needed */#endif	/* CONFIG_HW_WATCHDOG */#if defined(CONFIG_SERIAL_MULTI)		status = in8 (dev_base + UART_LSR);#else		status = in8 (ACTING_UART0_BASE + UART_LSR);#endif		if ((status & asyncLSRDataReady1) != 0x0) {			break;		}		if ((status & ( asyncLSRFramingError1 |				asyncLSROverrunError1 |				asyncLSRParityError1  |

⌨️ 快捷键说明

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