Ejemplo n.º 1
0
__initfunc(static enum uart check_uart(unsigned int iobase))
{
    unsigned char b1,b2,b3;
    enum uart u;
    enum uart uart_tab[] = { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };

    if (iobase <= 0 || iobase > 0x1000-SER_EXTENT)
        return c_uart_unknown;
    if (check_region(iobase, SER_EXTENT))
        return c_uart_unknown;
    b1 = inb(UART_MCR(iobase));
    outb(b1 | 0x10, UART_MCR(iobase));      /* loopback mode */
    b2 = inb(UART_MSR(iobase));
    outb(0x1a, UART_MCR(iobase));
    b3 = inb(UART_MSR(iobase)) & 0xf0;
    outb(b1, UART_MCR(iobase));        /* restore old values */
    outb(b2, UART_MSR(iobase));
    if (b3 != 0x90)
        return c_uart_unknown;
    inb(UART_RBR(iobase));
    inb(UART_RBR(iobase));
    outb(0x01, UART_FCR(iobase));           /* enable FIFOs */
    u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3];
    if (u == c_uart_16450) {
        outb(0x5a, UART_SCR(iobase));
        b1 = inb(UART_SCR(iobase));
        outb(0xa5, UART_SCR(iobase));
        b2 = inb(UART_SCR(iobase));
        if ((b1 != 0x5a) || (b2 != 0xa5))
            u = c_uart_8250;
    }
    return u;
}
Ejemplo n.º 2
0
/*
* This Function Wait until Data RX Ready, and return Data Read from UART.
*/
uint8_t uart_read_timeout(uart_num_t uart_num, uint32_t rx_timeout_nb_cycles, uart_error_t* error)
{
	uint32_t uart_port;
	uint8_t uart_val;
	uint32_t counter;

	uart_port = uart_num;

	/* Wait Until Data Received (Rx Data Not Ready) */
	counter = 0;
	while ((UART_LSR(uart_port) & UART_LSR_RDR) == 0)
	{
		if (rx_timeout_nb_cycles>0) {
			counter++;
			if (counter>=rx_timeout_nb_cycles) {
				*error = UART_TIMEOUT_ERROR;
				return 0;
			}
		}
	}

	uart_val = (UART_RBR(uart_port) & UART_RBR_MASKBIT);

	/* Clear error */
	*error = UART_NO_ERROR;

	return uart_val;
}
Ejemplo n.º 3
0
/*
* This Function Wait until Data RX Ready, and return Data Read from UART.
*/
uint8_t uart_read(uart_num_t uart_num)
{
	uint32_t uart_port;
	uint8_t uart_val;

	uart_port = uart_num;

	/* Wait Until Data Received (Rx Data Not Ready) */
	while ((UART_LSR(uart_port) & UART_LSR_RDR) == 0);

	uart_val = (UART_RBR(uart_port) & UART_RBR_MASKBIT);

	return uart_val;
}
/*
 * This is the serial driver's generic interrupt routine
 * Note: Generally it should be attached to general interrupt 10, responsile 
 *       for UART0&1 RCV and XMT interrupt, to make sure the invoked interrupt
 *       source, look into bit 10-13 of SIC_ISR(peripheral interrupt status reg.
 *       Finally, to see what can be done about request_irq(......)
 */
void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
	struct bf535_serial *info; // = &bf535_soft[CONFIG_SERIAL_CONSOLE_PORT];
	unsigned short iir; /* Interrupt Identification Register */
	unsigned short rx, idx;
	unsigned int sic_status = SIC_ISR;

	for (idx = 0; idx < NR_PORTS; idx++){
	   if (sic_status & (UART_INVOKED << 2*(idx + 5))){ 
	   	/* test bit 10-11 and 12-13 */
		iir = UART_IIR(idx);
		info = &bf535_soft[idx];

		if (!(iir & UART_IIR_NOINT)){
		   switch (iir & UART_IIR_STATUS){
		   case UART_IIR_LSR:
				printk("Line status changed for serial port %d.\n", idx);
				break;
		   case UART_IIR_RBR:
		   		/* Change access to IER & data port */
				ACCESS_PORT_IER(idx) 
				if (UART_LSR(idx) & UART_LSR_DR){
				   rx = UART_RBR(idx);
				   receive_chars(info, regs, rx);
				}
				break;
		   case UART_IIR_THR:
		   		/* Change access to IER & data port */
				ACCESS_PORT_IER(idx) 
				if (UART_LSR(idx) & UART_LSR_THRE){
				    transmit_chars(info);
//				    do{
//					transmit_chars(info);
//				    }while(info->xmit_cnt > 0);
				}
				break;
		   case UART_IIR_MSR:
				printk("Modem status changed for serial port.\n");
			
	   	   }
		}
	   }
	}	
Ejemplo n.º 5
0
int GetUARTBytes(u8 *buf, u32 size, u32 tmo_ms)
{
    u32 LSR;
    int tmo_en = (tmo_ms) ? 1 : 0;
    ulong start_time = get_timer(0);

    while (size) {
        if (tmo_en && (get_timer(start_time) > tmo_ms))
            break;

        /* kick watchdog to avoid cpu reset */
        if (!tmo_en)
            platform_wdt_kick();

        LSR = UART_READ32(UART_LSR(g_uart));
        if (LSR & UART_LSR_DR) {
            *buf++ = (u8)UART_READ32(UART_RBR(g_uart));
            size--;
        }
    }

    return (0 == size) ? 0 : -1;
}
Ejemplo n.º 6
0
int serial_nonblock_getc(void)
{
    return (int)UART_READ32(UART_RBR(g_uart));
}
Ejemplo n.º 7
0
/*
* UART Init function
*/
void uart_init(uart_num_t uart_num,
				uart_databit_t data_nb_bits,
				uart_stopbit_t data_nb_stop,
				uart_parity_t data_parity,
				uint16_t uart_divisor,
				uint8_t uart_divaddval,
				uint8_t uart_mulval)
{
	uint32_t lcr_config;
	uint32_t uart_port;

	uart_port = uart_num;

	switch(uart_num)
	{
		case UART0_NUM:
			/* use PLL1 as clock source for UART0 */
			CGU_BASE_UART0_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
			break;

		case UART1_NUM:
			/* use PLL1 as clock source for UART1 */
			CGU_BASE_UART1_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
			break;

		case UART2_NUM:
			/* use PLL1 as clock source for UART2 */
			CGU_BASE_UART2_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
			break;

		case UART3_NUM:
			/* use PLL1 as clock source for UART3 */
			CGU_BASE_UART3_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
			break;

		default:
			return; /* error */
	}

	/* FIFOs RX/TX Enabled and Reset RX/TX FIFO (DMA Mode is also cleared) */
	UART_FCR(uart_port) = ( UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS);
	/* Disable FIFO */
	UART_FCR(uart_port) = 0;

	// Dummy read (to clear existing data)
	while (UART_LSR(uart_port) & UART_LSR_RDR ) {
		dummy_read = UART_RBR(uart_port);
	}

	/* Wait end of TX & disable TX */
        UART_TER(uart_port) = UART_TER_TXEN;

        /* Wait for current transmit complete */
        while (!(UART_LSR(uart_port) & UART_LSR_THRE));

        /* Disable Tx */
        UART_TER(uart_port) = 0;

	/* Disable interrupt */
	UART_IER(uart_port) = 0;

	/* Set LCR to default state */
	UART_LCR(uart_port) = 0;

	/* Set ACR to default state */
	UART_ACR(uart_port) = 0;

	/* Dummy Read to Clear Status */
	dummy_read = UART_LSR(uart_port);

	/*
		Table 835. USART Fractional Divider Register:
		UARTbaudrate = PCLK / ( 16* (((256*DLM)+ DLL)*(1+(DivAddVal/MulVal))) )
		The value of MULVAL and DIVADDVAL should comply to the following conditions:
		1. 1 <= MULVAL <= 15
		2. 0 <= DIVADDVAL <= 14
		3. DIVADDVAL < MULVAL
	*/

	/* Set DLAB Bit */
	UART_LCR(uart_port) |= UART_LCR_DLAB_EN;
	UART_DLM(uart_port) = UART_LOAD_DLM(uart_divisor);
	UART_DLL(uart_port) = UART_LOAD_DLL(uart_divisor);
	/* Clear DLAB Bit */
	UART_LCR(uart_port) &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
	UART_FDR(uart_port) = (UART_FDR_MULVAL(uart_mulval) | UART_FDR_DIVADDVAL(uart_divaddval)) & UART_FDR_BITMASK;    

	/* Read LCR config & Force Enable of Divisor Latches Access */
	lcr_config = (UART_LCR(uart_port) & UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
	lcr_config |= data_nb_bits; /* Set Nb Data Bits */
	lcr_config |= data_nb_stop; /* Set Nb Stop Bits */
	lcr_config |= data_parity; /* Set Data Parity */

	/* Write LCR (only 8bits) */
	UART_LCR(uart_port) = (lcr_config & UART_LCR_BITMASK);

	/* Enable TX */
        UART_TER(uart_port) = UART_TER_TXEN;
}
static _INLINE_ void receive_chars(struct bf535_serial *info, struct pt_regs *regs, unsigned short rx)
{
	struct tty_struct *tty = info->tty;
	unsigned char ch;
	int idx = info->hub2;

	/*
	 * This do { } while() loop will get ALL chars out of Rx FIFO 
         */
	do {
		ch = (unsigned char) rx;
	
		if(info->is_cons) {
			if (UART_LSR(idx) & UART_LSR_BI){ /* break received */ 
				status_handle(info, UART_LSR(idx));
				return;
			} else if (ch == 0x10) { /* ^P */
				show_state();
				show_free_areas();
				show_buffers();
/*				show_net_buffers(); */
				return;
			} else if (ch == 0x12) { /* ^R */
				machine_restart(NULL);
				return;
			}
		}

		if(!tty){
			printk("no tty\n");
			goto clear_and_exit;
		}
		
		/*
		 * Make sure that we do not overflow the buffer
		 */
		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
			queue_task(&tty->flip.tqueue, &tq_timer);
			return;
		}

		if(UART_LSR(idx) & UART_LSR_PE) {
			*tty->flip.flag_buf_ptr++ = TTY_PARITY;
			status_handle(info, UART_LSR(idx));
		} else if(UART_LSR(idx) & UART_LSR_OE) {
			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
			status_handle(info, UART_LSR(idx));
		} else if(UART_LSR(idx) & UART_LSR_FE) {
			*tty->flip.flag_buf_ptr++ = TTY_FRAME;
			status_handle(info, UART_LSR(idx));
		} else {
			*tty->flip.flag_buf_ptr++ = 0; /* XXX */
		}

		tty->flip.count++;
                *tty->flip.char_buf_ptr++ = ch;

		ACCESS_PORT_IER(idx) /* change access to port data */
		rx = UART_RBR(idx);
	} while(UART_LSR(idx) & UART_LSR_DR);

	queue_task(&tty->flip.tqueue, &tq_timer);

clear_and_exit:
	return;
}