mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-31 03:58:17 +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 */
 |