📄 serial.c.svn-base
字号:
/* * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA *//*------------------------------------------------------------------------------+ *//* * This source code has been made available to you by IBM on an AS-IS * basis. Anyone receiving this source is licensed under IBM * copyrights to use it in any way he or she deems fit, including * copying it, modifying it, compiling it, and redistributing it either * with or without modifications. No license under IBM patents or * patent applications is to be implied by the copyright license. * * Any user of this software should understand that IBM cannot provide * technical support for this software and will not be responsible for * any consequences resulting from the use of this software. * * Any person who transfers this source code or any derivative work * must include the IBM copyright notice, this paragraph, and the * preceding two paragraphs in the transferred software. * * COPYRIGHT I B M CORPORATION 1995 * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M *//*------------------------------------------------------------------------------- */#include <common.h>#include <commproc.h>#include <asm/processor.h>#include <watchdog.h>#include "vecnum.h"#ifdef CONFIG_SERIAL_SOFTWARE_FIFO#include <malloc.h>#endif/*****************************************************************************/#ifdef CONFIG_IOP480#define SPU_BASE 0x40000000#define spu_LineStat_rc 0x00 /* Line Status Register (Read/Clear) */#define spu_LineStat_w 0x04 /* Line Status Register (Set) */#define spu_Handshk_rc 0x08 /* Handshake Status Register (Read/Clear) */#define spu_Handshk_w 0x0c /* Handshake Status Register (Set) */#define spu_BRateDivh 0x10 /* Baud rate divisor high */#define spu_BRateDivl 0x14 /* Baud rate divisor low */#define spu_CtlReg 0x18 /* Control Register */#define spu_RxCmd 0x1c /* Rx Command Register */#define spu_TxCmd 0x20 /* Tx Command Register */#define spu_RxBuff 0x24 /* Rx data buffer */#define spu_TxBuff 0x24 /* Tx data buffer *//*-----------------------------------------------------------------------------+ | Line Status Register. +-----------------------------------------------------------------------------*/#define asyncLSRport1 0x40000000#define asyncLSRport1set 0x40000004#define asyncLSRDataReady 0x80#define asyncLSRFramingError 0x40#define asyncLSROverrunError 0x20#define asyncLSRParityError 0x10#define asyncLSRBreakInterrupt 0x08#define asyncLSRTxHoldEmpty 0x04#define asyncLSRTxShiftEmpty 0x02/*-----------------------------------------------------------------------------+ | Handshake Status Register. +-----------------------------------------------------------------------------*/#define asyncHSRport1 0x40000008#define asyncHSRport1set 0x4000000c#define asyncHSRDsr 0x80#define asyncLSRCts 0x40/*-----------------------------------------------------------------------------+ | Control Register. +-----------------------------------------------------------------------------*/#define asyncCRport1 0x40000018#define asyncCRNormal 0x00#define asyncCRLoopback 0x40#define asyncCRAutoEcho 0x80#define asyncCRDtr 0x20#define asyncCRRts 0x10#define asyncCRWordLength7 0x00#define asyncCRWordLength8 0x08#define asyncCRParityDisable 0x00#define asyncCRParityEnable 0x04#define asyncCREvenParity 0x00#define asyncCROddParity 0x02#define asyncCRStopBitsOne 0x00#define asyncCRStopBitsTwo 0x01#define asyncCRDisableDtrRts 0x00/*-----------------------------------------------------------------------------+ | Receiver Command Register. +-----------------------------------------------------------------------------*/#define asyncRCRport1 0x4000001c#define asyncRCRDisable 0x00#define asyncRCREnable 0x80#define asyncRCRIntDisable 0x00#define asyncRCRIntEnabled 0x20#define asyncRCRDMACh2 0x40#define asyncRCRDMACh3 0x60#define asyncRCRErrorInt 0x10#define asyncRCRPauseEnable 0x08/*-----------------------------------------------------------------------------+ | Transmitter Command Register. +-----------------------------------------------------------------------------*/#define asyncTCRport1 0x40000020#define asyncTCRDisable 0x00#define asyncTCREnable 0x80#define asyncTCRIntDisable 0x00#define asyncTCRIntEnabled 0x20#define asyncTCRDMACh2 0x40#define asyncTCRDMACh3 0x60#define asyncTCRTxEmpty 0x10#define asyncTCRErrorInt 0x08#define asyncTCRStopPause 0x04#define asyncTCRBreakGen 0x02/*-----------------------------------------------------------------------------+ | Miscellanies defines. +-----------------------------------------------------------------------------*/#define asyncTxBufferport1 0x40000024#define asyncRxBufferport1 0x40000024#define asyncDLABLsbport1 0x40000014#define asyncDLABMsbport1 0x40000010#define asyncXOFFchar 0x13#define asyncXONchar 0x11/* * Minimal serial functions needed to use one of the SMC ports * as serial console interface. */int serial_init (void){ DECLARE_GLOBAL_DATA_PTR; volatile char val; unsigned short br_reg; br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); /* * Init onboard UART */ out8 (SPU_BASE + spu_LineStat_rc, 0x78); /* Clear all bits in Line Status Reg */ out8 (SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */ out8 (SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */ out8 (SPU_BASE + spu_CtlReg, 0x08); /* Set 8 bits, no parity and 1 stop bit */ out8 (SPU_BASE + spu_RxCmd, 0xb0); /* Enable Rx */ out8 (SPU_BASE + spu_TxCmd, 0x9c); /* Enable Tx */ out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ val = in8 (SPU_BASE + spu_RxBuff); /* Dummy read, to clear receiver */ return (0);}void serial_setbrg (void){ DECLARE_GLOBAL_DATA_PTR; unsigned short br_reg; br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1); out8 (SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */ out8 (SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */}void serial_putc (const char c){ if (c == '\n') serial_putc ('\r'); /* load status from handshake register */ if (in8 (SPU_BASE + spu_Handshk_rc) != 00) out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ out8 (SPU_BASE + spu_TxBuff, c); /* Put char */ while ((in8 (SPU_BASE + spu_LineStat_rc) & 04) != 04) { if (in8 (SPU_BASE + spu_Handshk_rc) != 00) out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */ }}void serial_puts (const char *s){ while (*s) { serial_putc (*s++); }}int serial_getc (){ unsigned char status = 0; while (1) { status = in8 (asyncLSRport1); if ((status & asyncLSRDataReady) != 0x0) { break; } if ((status & ( asyncLSRFramingError | asyncLSROverrunError | asyncLSRParityError | asyncLSRBreakInterrupt )) != 0) { (void) out8 (asyncLSRport1, asyncLSRFramingError | asyncLSROverrunError | asyncLSRParityError | asyncLSRBreakInterrupt ); } } return (0x000000ff & (int) in8 (asyncRxBufferport1));}int serial_tstc (){ unsigned char status; status = in8 (asyncLSRport1); if ((status & asyncLSRDataReady) != 0x0) { return (1); } if ((status & ( asyncLSRFramingError | asyncLSROverrunError | asyncLSRParityError | asyncLSRBreakInterrupt )) != 0) { (void) out8 (asyncLSRport1, asyncLSRFramingError | asyncLSROverrunError | asyncLSRParityError | asyncLSRBreakInterrupt); } return 0;}#endif /* CONFIG_IOP480 *//*****************************************************************************/#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405EP)#if defined(CONFIG_440)#define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000200#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000300#if defined(CONFIG_440_GX)#define CR0_MASK 0xdfffffff#define CR0_EXTCLK_ENA 0x00800000#define CR0_UDIV_POS 0#else#define CR0_MASK 0x3fff0000#define CR0_EXTCLK_ENA 0x00600000#define CR0_UDIV_POS 16#endif /* CONFIG_440_GX */#elif defined(CONFIG_405EP)#define UART0_BASE 0xef600300#define UART1_BASE 0xef600400#define UCR0_MASK 0x0000007f#define UCR1_MASK 0x00007f00#define UCR0_UDIV_POS 0#define UCR1_UDIV_POS 8#define UDIV_MAX 127#else /* CONFIG_405GP || CONFIG_405CR */#define UART0_BASE 0xef600300#define UART1_BASE 0xef600400#define CR0_MASK 0x00001fff#define CR0_EXTCLK_ENA 0x000000c0#define CR0_UDIV_POS 1#define UDIV_MAX 32#endif/* using serial port 0 or 1 as U-Boot console ? */#if defined(CONFIG_UART1_CONSOLE)#define ACTING_UART0_BASE UART1_BASE#define ACTING_UART1_BASE UART0_BASE#if defined(CONFIG_440_GX)#define UART0_SDR sdr_uart1#define UART1_SDR sdr_uart0#endif /* CONFIG_440_GX */#else#define ACTING_UART0_BASE UART0_BASE#define ACTING_UART1_BASE UART1_BASE#if defined(CONFIG_440_GX)#define UART0_SDR sdr_uart0#define UART1_SDR sdr_uart1#endif /* CONFIG_440_GX */#endif#if defined(CONFIG_405EP) && defined(CFG_EXT_SERIAL_CLOCK)#error "External serial clock not supported on IBM PPC405EP!"#endif#define UART_RBR 0x00#define UART_THR 0x00#define UART_IER 0x01#define UART_IIR 0x02#define UART_FCR 0x02#define UART_LCR 0x03#define UART_MCR 0x04#define UART_LSR 0x05#define UART_MSR 0x06#define UART_SCR 0x07#define UART_DLL 0x00#define UART_DLM 0x01/*-----------------------------------------------------------------------------+ | Line Status Register. +-----------------------------------------------------------------------------*//*#define asyncLSRport1 ACTING_UART0_BASE+0x05 */#define asyncLSRDataReady1 0x01#define asyncLSROverrunError1 0x02#define asyncLSRParityError1 0x04#define asyncLSRFramingError1 0x08#define asyncLSRBreakInterrupt1 0x10#define asyncLSRTxHoldEmpty1 0x20#define asyncLSRTxShiftEmpty1 0x40#define asyncLSRRxFifoError1 0x80/*-----------------------------------------------------------------------------+ | Miscellanies defines. +-----------------------------------------------------------------------------*//*#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)int serial_init (void){ DECLARE_GLOBAL_DATA_PTR; unsigned long reg; unsigned long udiv; unsigned short bdiv; volatile char val;#ifdef CFG_EXT_SERIAL_CLOCK unsigned long tmp;#endif#if defined(CONFIG_440_GX) mfsdr(UART0_SDR,reg); reg &= ~CR0_MASK;#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -