mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	- Add support for Altera FPGA ACEX1K
* Patches by Thomas Lange, 09 Oct 2003:
  - Endian swap ATA identity for all big endian CPUs, not just PPC
  - MIPS only: New option CONFIG_MEMSIZE_IN_BYTES for passing memsize
    args to linux
  - add support for dbau1x00 board (MIPS32)
		
	
			
		
			
				
	
	
		
			372 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			372 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (INCA) ASC UART support
 | 
						|
 */
 | 
						|
 | 
						|
#include <config.h>
 | 
						|
 | 
						|
#if defined(CONFIG_PURPLE) || defined(CONFIG_INCA_IP)
 | 
						|
 | 
						|
#ifdef CONFIG_PURPLE
 | 
						|
#define	serial_init	asc_serial_init
 | 
						|
#define	serial_putc	asc_serial_putc
 | 
						|
#define	serial_puts	asc_serial_puts
 | 
						|
#define	serial_getc	asc_serial_getc
 | 
						|
#define	serial_tstc	asc_serial_tstc
 | 
						|
#define	serial_setbrg	asc_serial_setbrg
 | 
						|
#endif
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <asm/inca-ip.h>
 | 
						|
#include "asc_serial.h"
 | 
						|
 | 
						|
#ifdef CONFIG_PURPLE
 | 
						|
 | 
						|
#undef ASC_FIFO_PRESENT
 | 
						|
#define TOUT_LOOP	100000
 | 
						|
 | 
						|
/* Set base address for second FPI interrupt control register bank */
 | 
						|
#define SFPI_INTCON_BASEADDR	0xBF0F0000
 | 
						|
 | 
						|
/* Register offset from base address */
 | 
						|
#define FBS_ISR		0x00000000	/* Interrupt status register */
 | 
						|
#define FBS_IMR		0x00000008	/* Interrupt mask register */
 | 
						|
#define FBS_IDIS	0x00000010	/* Interrupt disable register */
 | 
						|
 | 
						|
/* Interrupt status register bits */
 | 
						|
#define FBS_ISR_AT	0x00000040	/* ASC transmit interrupt */
 | 
						|
#define FBS_ISR_AR 	0x00000020	/* ASC receive interrupt */
 | 
						|
#define FBS_ISR_AE	0x00000010	/* ASC error interrupt */
 | 
						|
#define FBS_ISR_AB	0x00000008	/* ASC transmit buffer interrupt */
 | 
						|
#define FBS_ISR_AS      0x00000004 	/* ASC start of autobaud detection interrupt */
 | 
						|
#define FBS_ISR_AF	0x00000002	/* ASC end of autobaud detection interrupt */
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
#define ASC_FIFO_PRESENT
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
#define SET_BIT(reg, mask)                  reg |= (mask)
 | 
						|
#define CLEAR_BIT(reg, mask)                reg &= (~mask)
 | 
						|
#define CLEAR_BITS(reg, mask)               CLEAR_BIT(reg, mask)
 | 
						|
#define SET_BITS(reg, mask)                 SET_BIT(reg, mask)
 | 
						|
#define SET_BITFIELD(reg, mask, off, val)   {reg &= (~mask); reg |= (val << off);}
 | 
						|
 | 
						|
extern uint incaip_get_fpiclk(void);
 | 
						|
 | 
						|
static int serial_setopt (void);
 | 
						|
 | 
						|
/* pointer to ASC register base address */
 | 
						|
static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
 | 
						|
 | 
						|
/******************************************************************************
 | 
						|
*
 | 
						|
* serial_init - initialize a INCAASC channel
 | 
						|
*
 | 
						|
* This routine initializes the number of data bits, parity
 | 
						|
* and set the selected baud rate. Interrupts are disabled.
 | 
						|
* Set the modem control signals if the option is selected.
 | 
						|
*
 | 
						|
* RETURNS: N/A
 | 
						|
*/
 | 
						|
 | 
						|
int serial_init (void)
 | 
						|
{
 | 
						|
#ifdef CONFIG_INCA_IP
 | 
						|
    /* we have to set PMU.EN13 bit to enable an ASC device*/
 | 
						|
    INCAASC_PMU_ENABLE(13);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* and we have to set CLC register*/
 | 
						|
    CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
 | 
						|
    SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
 | 
						|
 | 
						|
    /* initialy we are in async mode */
 | 
						|
    pAsc->asc_con = ASCCON_M_8ASYNC;
 | 
						|
 | 
						|
    /* select input port */
 | 
						|
    pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
 | 
						|
 | 
						|
#ifdef ASC_FIFO_PRESENT
 | 
						|
    /* TXFIFO's filling level */
 | 
						|
    SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
 | 
						|
		    ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
 | 
						|
    /* enable TXFIFO */
 | 
						|
    SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
 | 
						|
 | 
						|
    /* RXFIFO's filling level */
 | 
						|
    SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
 | 
						|
		    ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
 | 
						|
    /* enable RXFIFO */
 | 
						|
    SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* enable error signals */
 | 
						|
    SET_BIT(pAsc->asc_con, ASCCON_FEN);
 | 
						|
    SET_BIT(pAsc->asc_con, ASCCON_OEN);
 | 
						|
 | 
						|
#ifdef CONFIG_INCA_IP
 | 
						|
    /* acknowledge ASC interrupts */
 | 
						|
    ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
 | 
						|
 | 
						|
    /* disable ASC interrupts */
 | 
						|
    ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef ASC_FIFO_PRESENT
 | 
						|
    /* set FIFOs into the transparent mode */
 | 
						|
    SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
 | 
						|
    SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
 | 
						|
#endif
 | 
						|
 | 
						|
    /* set baud rate */
 | 
						|
    serial_setbrg();
 | 
						|
 | 
						|
    /* set the options */
 | 
						|
    serial_setopt();
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void serial_setbrg (void)
 | 
						|
{
 | 
						|
    ulong      uiReloadValue, fdv;
 | 
						|
    ulong      f_ASC;
 | 
						|
 | 
						|
#ifdef CONFIG_INCA_IP
 | 
						|
    f_ASC = incaip_get_fpiclk();
 | 
						|
#else
 | 
						|
    f_ASC = ASC_CLOCK_RATE;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef INCAASC_USE_FDV
 | 
						|
    fdv = 2;
 | 
						|
    uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
 | 
						|
#else
 | 
						|
    fdv = INCAASC_FDV_HIGH_BAUDRATE;
 | 
						|
    uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
 | 
						|
#endif /* INCAASC_USE_FDV */
 | 
						|
 | 
						|
    if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
 | 
						|
    {
 | 
						|
#ifndef INCAASC_USE_FDV
 | 
						|
	fdv = 3;
 | 
						|
	uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
 | 
						|
#else
 | 
						|
	fdv = INCAASC_FDV_LOW_BAUDRATE;
 | 
						|
	uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
 | 
						|
#endif /* INCAASC_USE_FDV */
 | 
						|
 | 
						|
	if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
 | 
						|
	{
 | 
						|
	    return;    /* can't impossibly generate that baud rate */
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /* Disable Baud Rate Generator; BG should only be written when R=0 */
 | 
						|
    CLEAR_BIT(pAsc->asc_con, ASCCON_R);
 | 
						|
 | 
						|
#ifndef INCAASC_USE_FDV
 | 
						|
    /*
 | 
						|
     * Disable Fractional Divider (FDE)
 | 
						|
     * Divide clock by reload-value + constant (BRS)
 | 
						|
     */
 | 
						|
    /* FDE = 0 */
 | 
						|
    CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
 | 
						|
 | 
						|
    if ( fdv == 2 )
 | 
						|
	CLEAR_BIT(pAsc->asc_con, ASCCON_BRS);   /* BRS = 0 */
 | 
						|
    else
 | 
						|
	SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
 | 
						|
 | 
						|
#else /* INCAASC_USE_FDV */
 | 
						|
 | 
						|
    /* Enable Fractional Divider */
 | 
						|
    SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
 | 
						|
 | 
						|
    /* Set fractional divider value */
 | 
						|
    pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
 | 
						|
 | 
						|
#endif /* INCAASC_USE_FDV */
 | 
						|
 | 
						|
    /* Set reload value in BG */
 | 
						|
    pAsc->asc_bg = uiReloadValue;
 | 
						|
 | 
						|
    /* Enable Baud Rate Generator */
 | 
						|
    SET_BIT(pAsc->asc_con, ASCCON_R);           /* R = 1 */
 | 
						|
}
 | 
						|
 | 
						|
/*******************************************************************************
 | 
						|
*
 | 
						|
* serial_setopt - set the serial options
 | 
						|
*
 | 
						|
* Set the channel operating mode to that specified. Following options
 | 
						|
* are supported: CREAD, CSIZE, PARENB, and PARODD.
 | 
						|
*
 | 
						|
* Note, this routine disables the transmitter.  The calling routine
 | 
						|
* may have to re-enable it.
 | 
						|
*
 | 
						|
* RETURNS:
 | 
						|
* Returns 0 to indicate success, otherwise -1 is returned
 | 
						|
*/
 | 
						|
 | 
						|
static int serial_setopt (void)
 | 
						|
{
 | 
						|
    ulong  con;
 | 
						|
 | 
						|
    switch ( ASC_OPTIONS & ASCOPT_CSIZE )
 | 
						|
    {
 | 
						|
    /* 7-bit-data */
 | 
						|
    case ASCOPT_CS7:
 | 
						|
	con = ASCCON_M_7ASYNCPAR;   /* 7-bit-data and parity bit */
 | 
						|
	break;
 | 
						|
 | 
						|
    /* 8-bit-data */
 | 
						|
    case ASCOPT_CS8:
 | 
						|
	if ( ASC_OPTIONS & ASCOPT_PARENB )
 | 
						|
	    con = ASCCON_M_8ASYNCPAR;   /* 8-bit-data and parity bit */
 | 
						|
	else
 | 
						|
	    con = ASCCON_M_8ASYNC;      /* 8-bit-data no parity */
 | 
						|
	break;
 | 
						|
 | 
						|
    /*
 | 
						|
     *  only 7 and 8-bit frames are supported
 | 
						|
     *  if we don't use IOCTL extensions
 | 
						|
     */
 | 
						|
    default:
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    if ( ASC_OPTIONS & ASCOPT_STOPB )
 | 
						|
	SET_BIT(con, ASCCON_STP);       /* 2 stop bits */
 | 
						|
    else
 | 
						|
	CLEAR_BIT(con, ASCCON_STP);     /* 1 stop bit */
 | 
						|
 | 
						|
    if ( ASC_OPTIONS & ASCOPT_PARENB )
 | 
						|
	SET_BIT(con, ASCCON_PEN);           /* enable parity checking */
 | 
						|
    else
 | 
						|
	CLEAR_BIT(con, ASCCON_PEN);         /* disable parity checking */
 | 
						|
 | 
						|
    if ( ASC_OPTIONS & ASCOPT_PARODD )
 | 
						|
	SET_BIT(con, ASCCON_ODD);       /* odd parity */
 | 
						|
    else
 | 
						|
	CLEAR_BIT(con, ASCCON_ODD);     /* even parity */
 | 
						|
 | 
						|
    if ( ASC_OPTIONS & ASCOPT_CREAD )
 | 
						|
	SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
 | 
						|
 | 
						|
    pAsc->asc_con |= con;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void serial_putc (const char c)
 | 
						|
{
 | 
						|
#ifdef ASC_FIFO_PRESENT
 | 
						|
    uint txFl = 0;
 | 
						|
#else
 | 
						|
    uint timeout = 0;
 | 
						|
#endif
 | 
						|
 | 
						|
    if (c == '\n') serial_putc ('\r');
 | 
						|
 | 
						|
#ifdef ASC_FIFO_PRESENT
 | 
						|
    /* check do we have a free space in the TX FIFO */
 | 
						|
    /* get current filling level */
 | 
						|
    do
 | 
						|
    {
 | 
						|
	txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
 | 
						|
    }
 | 
						|
    while ( txFl == INCAASC_TXFIFO_FULL );
 | 
						|
#else
 | 
						|
 | 
						|
    while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
 | 
						|
			   FBS_ISR_AB))
 | 
						|
    {
 | 
						|
	    if (timeout++ > TOUT_LOOP)
 | 
						|
	    {
 | 
						|
		    break;
 | 
						|
	    }
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
 | 
						|
 | 
						|
#ifndef ASC_FIFO_PRESENT
 | 
						|
    *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AB |
 | 
						|
								 FBS_ISR_AT;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* check for errors */
 | 
						|
    if ( pAsc->asc_con & ASCCON_OE )
 | 
						|
    {
 | 
						|
	SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void serial_puts (const char *s)
 | 
						|
{
 | 
						|
    while (*s)
 | 
						|
    {
 | 
						|
	serial_putc (*s++);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int serial_getc (void)
 | 
						|
{
 | 
						|
    ulong symbol_mask;
 | 
						|
    char c;
 | 
						|
 | 
						|
    while (!serial_tstc());
 | 
						|
 | 
						|
    symbol_mask =
 | 
						|
	((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
 | 
						|
 | 
						|
    c = (char)(pAsc->asc_rbuf & symbol_mask);
 | 
						|
 | 
						|
#ifndef ASC_FIFO_PRESENT
 | 
						|
    *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AR;
 | 
						|
#endif
 | 
						|
 | 
						|
    return c;
 | 
						|
}
 | 
						|
 | 
						|
int serial_tstc (void)
 | 
						|
{
 | 
						|
    int res = 1;
 | 
						|
 | 
						|
#ifdef ASC_FIFO_PRESENT
 | 
						|
    if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
 | 
						|
    {
 | 
						|
	res = 0;
 | 
						|
    }
 | 
						|
#else
 | 
						|
    if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
 | 
						|
								FBS_ISR_AR))
 | 
						|
 | 
						|
    {
 | 
						|
	res = 0;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    else if ( pAsc->asc_con & ASCCON_FE )
 | 
						|
    {
 | 
						|
	SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
 | 
						|
	res = 0;
 | 
						|
    }
 | 
						|
    else if ( pAsc->asc_con & ASCCON_PE )
 | 
						|
    {
 | 
						|
	SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
 | 
						|
	res = 0;
 | 
						|
    }
 | 
						|
    else if ( pAsc->asc_con & ASCCON_OE )
 | 
						|
    {
 | 
						|
	SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
 | 
						|
	res = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    return res;
 | 
						|
}
 | 
						|
#endif /* CONFIG_PURPLE || CONFIG_INCA_IP */
 |