2005-04-16 15:20:36 -07:00
/*
* serialGT . c
*
* BRIEF MODULE DESCRIPTION
* Low Level Serial Port control for use
* with the Galileo EVB64120A MIPS eval board and
* its on board two channel 16552 Uart .
*
* Copyright ( C ) 2000 RidgeRun , Inc .
* Author : RidgeRun , Inc .
* glonnon @ ridgerun . com , skranz @ ridgerun . com , stevej @ ridgerun . com
*
* 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 SOFTWARE IS PROVIDED ` ` AS IS ' ' AND ANY EXPRESS OR IMPLIED
* WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF
* USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* 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 . ,
* 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
*/
// Note:
// Serial CHANNELS - 0 is the bottom connector of evb64120A.
// (The one that maps to the "B" channel of the
// board's uart)
// 1 is the top connector of evb64120A.
// (The one that maps to the "A" channel of the
// board's uart)
int DEBUG_CHANNEL = 0 ; // See Note Above
int CONSOLE_CHANNEL = 1 ; // See Note Above
# define DUART 0xBD000000 /* Base address of Uart. */
# define CHANNELOFFSET 0x20 / * DUART+CHANNELOFFSET gets you to the ChanA
register set of the 16552 Uart device .
DUART + 0 gets you to the ChanB register set .
*/
# define DUART_DELTA 0x4
# define FIFO_ENABLE 0x07
# define INT_ENABLE 0x04 /* default interrupt mask */
# define RBR 0x00
# define THR 0x00
# define DLL 0x00
# define IER 0x01
# define DLM 0x01
# define IIR 0x02
# define FCR 0x02
# define LCR 0x03
# define MCR 0x04
# define LSR 0x05
# define MSR 0x06
# define SCR 0x07
# define LCR_DLAB 0x80
# define XTAL 1843200
# define LSR_THRE 0x20
# define LSR_BI 0x10
# define LSR_DR 0x01
# define MCR_LOOP 0x10
# define ACCESS_DELAY 0x10000
/******************************
Routine :
Description :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int inreg ( int channel , int reg )
{
int val ;
val =
* ( ( volatile unsigned char * ) DUART +
( channel * CHANNELOFFSET ) + ( reg * DUART_DELTA ) ) ;
return val ;
}
/******************************
Routine :
Description :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void outreg ( int channel , int reg , unsigned char val )
{
* ( ( volatile unsigned char * ) DUART + ( channel * CHANNELOFFSET )
+ ( reg * DUART_DELTA ) ) = val ;
}
/******************************
Routine :
Description :
Initialize the device driver .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void serial_init ( int channel )
{
/*
* Configure active port , ( CHANNELOFFSET already set . )
*
* Set 8 bits , 1 stop bit , no parity .
*
* LCR < 7 > 0 divisor latch access bit
* LCR < 6 > 0 break control ( 1 = send break )
* LCR < 5 > 0 stick parity ( 0 = space , 1 = mark )
* LCR < 4 > 0 parity even ( 0 = odd , 1 = even )
* LCR < 3 > 0 parity enable ( 1 = enabled )
* LCR < 2 > 0 # stop bits ( 0 = 1 , 1 = 1.5 )
* LCR < 1 : 0 > 11 bits per character ( 00 = 5 , 01 = 6 , 10 = 7 , 11 = 8 )
*/
outreg ( channel , LCR , 0x3 ) ;
outreg ( channel , FCR , FIFO_ENABLE ) ; /* Enable the FIFO */
outreg ( channel , IER , INT_ENABLE ) ; /* Enable appropriate interrupts */
}
/******************************
Routine :
Description :
Set the baud rate .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void serial_set ( int channel , unsigned long baud )
{
unsigned char sav_lcr ;
/*
* Enable access to the divisor latches by setting DLAB in LCR .
*
*/
sav_lcr = inreg ( channel , LCR ) ;
#if 0
/*
* Set baud rate
*/
outreg ( channel , LCR , LCR_DLAB | sav_lcr ) ;
// outreg(DLL,(XTAL/(16*2*(baud))-2));
outreg ( channel , DLL , XTAL / ( 16 * baud ) ) ;
// outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
outreg ( channel , DLM , ( XTAL / ( 16 * baud ) ) > > 8 ) ;
# else
/*
* Note : Set baud rate , hardcoded here for rate of 115200
2006-06-05 10:45:30 +01:00
* since became unsure of above " baud rate " algorithm ( ? ? ) .
2005-04-16 15:20:36 -07:00
*/
outreg ( channel , LCR , 0x83 ) ;
outreg ( channel , DLM , 0x00 ) ; // See note above
outreg ( channel , DLL , 0x02 ) ; // See note above.
outreg ( channel , LCR , 0x03 ) ;
# endif
/*
* Restore line control register
*/
outreg ( channel , LCR , sav_lcr ) ;
}
/******************************
Routine :
Description :
Transmit a character .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void serial_putc ( int channel , int c )
{
while ( ( inreg ( channel , LSR ) & LSR_THRE ) = = 0 ) ;
outreg ( channel , THR , c ) ;
}
/******************************
Routine :
Description :
Read a received character if one is
available . Return - 1 otherwise .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int serial_getc ( int channel )
{
if ( inreg ( channel , LSR ) & LSR_DR ) {
return inreg ( channel , RBR ) ;
}
return - 1 ;
}
/******************************
Routine :
Description :
Used by embedded gdb client . ( example ; gdb - stub . c )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char getDebugChar ( )
{
int val ;
while ( ( val = serial_getc ( DEBUG_CHANNEL ) ) = = - 1 ) ; // loop until we get a character in.
return ( char ) val ;
}
/******************************
Routine :
Description :
Used by embedded gdb target . ( example ; gdb - stub . c )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void putDebugChar ( char c )
{
serial_putc ( DEBUG_CHANNEL , ( int ) c ) ;
}